removed clist flag : GTK_CLIST_DRAG_SELECTION added flags :
authorLars Hamann <lars@gtk.org>
Wed, 16 Dec 1998 01:28:31 +0000 (01:28 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Wed, 16 Dec 1998 01:28:31 +0000 (01:28 +0000)
Tue Dec 15 22:30:44 1998  Lars Hamann  <lars@gtk.org>

* gtk/gtkclist.h :
removed clist flag : GTK_CLIST_DRAG_SELECTION
added flags : GTK_CLIST_REORDERABLE, GTK_CLIST_USE_DRAG_ICONS,
GTK_CLIST_DRAW_DRAG_LINE, GTK_CLIST_DRAW_DRAG_RECT
(GtkCListDragPos) : new enum for DND
  (GtkButtonAction) : new enum of possible mouse button actions
(struct _GtkCList): added button_actions array.
  Added drag_button and click_cell struct, to store cell and
  mouse button of last button_press_event

(struct _GtkCListClass): new class method draw_drag_highlight.
(gtk_clist_set_reorderable) (gtk_clist_set_use_drag_icons) :
new functions. Moved from gtkctree.h. Now clist is reorderable
as well.
(gtk_clist_set_button_actions) new function to customize mouse
button actions.

* gtk/gtkclist.c:
(gtk_clist_drag_begin)
(gtk_clist_drag_motion)
(gtk_clist_drag_leave)
(gtk_clist_drag_end)
(gtk_clist_drag_drop)
(gtk_clist_drag_data_get)
(gtk_clist_drag_data_received) : new dnd widget methods to
implement clists reorderability via DND

(remove_grab) : new function. remove mouse grab if necessary.
(draw_drag_highlight) : new method. Draw dnd highlight depending
on clist flags GTK_CLIST_DRAW_DRAG_LINE and GTK_CLIST_DRAW_DRAG_RECT

(gtk_clist_class_init): added object args "reorderable" and
  "use_drag_icons"

(gtk_clist_button_press) (gtk_clist_button_release) :
use button_actions array to decide which action to perform.
(gtk_clist_motion) : start reorder operation if necessary.

* gtk/gtkctree.h :
(struct _GtkCTree): removed drag_icon, icon_widht, icon_height,
drag_row, drag_source, drag_target, reorderable, use_icons,
in_drag, drag_rect
(gtk_ctree_set_reorderable) :  deprecated function.
  use gtk_clist_set_reorderable instead.
(gtk_ctree_set_use_drag_icons) : deprecated function.
  use gtk_clist_set_use_drag_icons instead.

* gtk/gtkctree.c :
(gtk_ctree_class_init): removed object args "reorderable" and
and "use_drag_icons"

(draw_xor_line) (draw_xor_rect) (create_drag_icon) (check_cursor)
(tree_toggle_selection) (set_mouse_cursor) : removed

(draw_drag_highlight) : new clist method. replacement for
draw_xor_line and draw_xor_rect functions
(check_drag) renamed check_cursor function

(gtk_ctree_drag_begin)
(gtk_ctree_drag_motion)
(gtk_ctree_drag_data_received) : new dnd methods to implement ctrees
reorderability via DND

(gtk_ctree_button_release)
(gtk_ctree_button_motion) : removed.

* gtk/testgtk.c:
(create_clist) : added new reorderable toggle button

gtk/gtkclist.c
gtk/gtkclist.h
gtk/gtkctree.c
gtk/gtkctree.h
gtk/testgtk.c
tests/testgtk.c

index ca65edfd311eeaddbf420711b154f5828adea8d4..8b6b92c561698dcb08c66f8f6c0c9fdb1d5fe9de 100644 (file)
 #include "gtkmain.h"
 #include "gtkclist.h"
 #include "gtkbindings.h"
+#include "gtkdnd.h"
 #include "gtkprivate.h"
+#include <gdk/gdkx.h>
 #include <gdk/gdkkeysyms.h>
 
+/* length of button_actions array */
+#define MAX_BUTTON 5
+
 /* the number rows memchunk expands at a time */
 #define CLIST_OPTIMUM_SIZE 512
 
@@ -154,7 +159,9 @@ enum {
   ARG_N_COLUMNS,
   ARG_SHADOW_TYPE,
   ARG_SELECTION_MODE,
-  ARG_ROW_HEIGHT
+  ARG_ROW_HEIGHT,
+  ARG_REORDERABLE,
+  ARG_USE_DRAG_ICONS,
 };
 
 /* GtkCList Methods */
@@ -204,6 +211,35 @@ static gint gtk_clist_focus           (GtkContainer     *container,
                                       GtkDirectionType  direction);
 static void gtk_clist_style_set       (GtkWidget        *widget,
                                       GtkStyle         *previous_style);
+static void gtk_clist_drag_begin      (GtkWidget        *widget,
+                                      GdkDragContext   *context);
+static gint gtk_clist_drag_motion     (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      gint              x,
+                                      gint              y,
+                                      guint             time);
+static void gtk_clist_drag_leave      (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      guint             time);
+static void gtk_clist_drag_end        (GtkWidget        *widget,
+                                      GdkDragContext   *context);
+static gboolean gtk_clist_drag_drop   (GtkWidget      *widget,
+                                      GdkDragContext *context,
+                                      gint            x,
+                                      gint            y,
+                                      guint           time);
+static void gtk_clist_drag_data_get   (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      GtkSelectionData *selection_data,
+                                      guint             info,
+                                      guint             time);
+static void gtk_clist_drag_data_received (GtkWidget        *widget,
+                                         GdkDragContext   *context,
+                                         gint              x,
+                                         gint              y,
+                                         GtkSelectionData *selection_data,
+                                         guint             info,
+                                         guint32           time);
 
 /* GtkContainer Methods */
 static void gtk_clist_set_focus_child (GtkContainer  *container,
@@ -256,15 +292,6 @@ static void start_selection           (GtkCList      *clist);
 static void end_selection             (GtkCList      *clist);
 static void toggle_add_mode           (GtkCList      *clist);
 static void toggle_focus_row          (GtkCList      *clist);
-static void move_focus_row            (GtkCList      *clist,
-                                      GtkScrollType  scroll_type,
-                                      gfloat         position);
-static void scroll_horizontal         (GtkCList      *clist,
-                                      GtkScrollType  scroll_type,
-                                      gfloat         position);
-static void scroll_vertical           (GtkCList      *clist,
-                                      GtkScrollType  scroll_type,
-                                      gfloat         position);
 static void extend_selection          (GtkCList      *clist,
                                       GtkScrollType  scroll_type,
                                       gfloat         position,
@@ -275,6 +302,26 @@ static gint get_selection_info        (GtkCList       *clist,
                                       gint           *row,
                                       gint           *column);
 
+/* Scrolling */
+static void move_focus_row     (GtkCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void scroll_horizontal  (GtkCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void scroll_vertical    (GtkCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void move_horizontal    (GtkCList      *clist,
+                               gint           diff);
+static void move_vertical      (GtkCList      *clist,
+                               gint           row,
+                               gfloat         align);
+static gint horizontal_timeout (GtkCList      *clist);
+static gint vertical_timeout   (GtkCList      *clist);
+static void remove_grab        (GtkCList      *clist);
+
+
 /* Resize Columns */
 static void draw_xor_line             (GtkCList       *clist);
 static gint new_column_width          (GtkCList       *clist,
@@ -336,6 +383,10 @@ static void draw_row         (GtkCList      *clist,
 static void draw_rows        (GtkCList      *clist,
                              GdkRectangle  *area);
 static void clist_refresh    (GtkCList      *clist);
+static void draw_drag_highlight (GtkCList        *clist,
+                                GtkCListRow     *dest_row,
+                                gint             dest_row_number,
+                                GtkCListDragPos  drag_pos);
      
 /* Size Allocation / Requisition */
 static void size_allocate_title_buttons (GtkCList *clist);
@@ -386,9 +437,11 @@ static void real_row_move   (GtkCList *clist,
                             gint      dest_row);
 
 
+
 static GtkContainerClass *parent_class = NULL;
 static guint clist_signals[LAST_SIGNAL] = {0};
 
+static GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
 
 GtkType
 gtk_clist_get_type (void)
@@ -444,6 +497,14 @@ gtk_clist_class_init (GtkCListClass *klass)
                           GTK_TYPE_UINT,
                           GTK_ARG_READWRITE,
                           ARG_ROW_HEIGHT);
+  gtk_object_add_arg_type ("GtkCList::reorderable",
+                          GTK_TYPE_BOOL,
+                          GTK_ARG_READWRITE,
+                          ARG_REORDERABLE);
+  gtk_object_add_arg_type ("GtkCList::use_drag_icons",
+                          GTK_TYPE_BOOL,
+                          GTK_ARG_READWRITE,
+                          ARG_USE_DRAG_ICONS);
   
   object_class->set_arg = gtk_clist_set_arg;
   object_class->get_arg = gtk_clist_get_arg;
@@ -595,6 +656,13 @@ gtk_clist_class_init (GtkCListClass *klass)
   widget_class->focus_out_event = gtk_clist_focus_out;
   widget_class->draw_focus = gtk_clist_draw_focus;
   widget_class->style_set = gtk_clist_style_set;
+  widget_class->drag_begin = gtk_clist_drag_begin;
+  widget_class->drag_end = gtk_clist_drag_end;
+  widget_class->drag_motion = gtk_clist_drag_motion;
+  widget_class->drag_leave = gtk_clist_drag_leave;
+  widget_class->drag_drop = gtk_clist_drag_drop;
+  widget_class->drag_data_get = gtk_clist_drag_data_get;
+  widget_class->drag_data_received = gtk_clist_drag_data_received;
 
   /* container_class->add = NULL; use the default GtkContainerClass warning */
   /* container_class->remove=NULL; use the default GtkContainerClass warning */
@@ -614,6 +682,7 @@ gtk_clist_class_init (GtkCListClass *klass)
   klass->click_column = NULL;
   klass->resize_column = real_resize_column;
   klass->draw_row = draw_row;
+  klass->draw_drag_highlight = draw_drag_highlight;
   klass->insert_row = real_insert_row;
   klass->remove_row = real_remove_row;
   klass->clear = real_clear;
@@ -854,6 +923,12 @@ gtk_clist_set_arg (GtkObject      *object,
     case ARG_ROW_HEIGHT:
       gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg));
       break;
+    case ARG_REORDERABLE:
+      gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg));
+      break;
+    case ARG_USE_DRAG_ICONS:
+      gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg));
+      break;
     default:
       break;
     }
@@ -880,7 +955,13 @@ gtk_clist_get_arg (GtkObject      *object,
       GTK_VALUE_ENUM (*arg) = clist->selection_mode;
       break;
     case ARG_ROW_HEIGHT:
-      GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET (clist) ? clist->row_height : 0;
+      GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0;
+      break;
+    case ARG_REORDERABLE:
+      GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist);
+      break;
+    case ARG_USE_DRAG_ICONS:
+      GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist);
       break;
     default:
       arg->type = GTK_TYPE_INVALID;
@@ -894,6 +975,10 @@ gtk_clist_init (GtkCList *clist)
   clist->flags = 0;
 
   GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
+  GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
+  GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
+  GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE);
+  GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
 
   clist->row_mem_chunk = NULL;
   clist->cell_mem_chunk = NULL;
@@ -925,6 +1010,12 @@ gtk_clist_init (GtkCList *clist)
   clist->vadjustment = NULL;
   clist->hadjustment = NULL;
 
+  clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS;
+  clist->button_actions[1] = GTK_BUTTON_IGNORED;
+  clist->button_actions[2] = GTK_BUTTON_IGNORED;
+  clist->button_actions[3] = GTK_BUTTON_IGNORED;
+  clist->button_actions[4] = GTK_BUTTON_IGNORED;
+
   clist->cursor_drag = NULL;
   clist->xor_gc = NULL;
   clist->fg_gc = NULL;
@@ -937,8 +1028,6 @@ gtk_clist_init (GtkCList *clist)
   clist->undo_selection = NULL;
   clist->undo_unselection = NULL;
 
-  GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
-  GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
   clist->focus_row = -1;
   clist->undo_anchor = -1;
 
@@ -948,6 +1037,9 @@ gtk_clist_init (GtkCList *clist)
   clist->htimer = 0;
   clist->vtimer = 0;
 
+  clist->click_cell.row = -1;
+  clist->click_cell.column = -1;
+
   clist->compare = default_compare;
   clist->sort_type = GTK_SORT_ASCENDING;
   clist->sort_column = 0;
@@ -1252,7 +1344,7 @@ gtk_clist_column_titles_show (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (!GTK_CLIST_SHOW_TITLES (clist))
+  if (!GTK_CLIST_SHOW_TITLES(clist))
     {
       GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
       if (clist->title_window)
@@ -1267,7 +1359,7 @@ gtk_clist_column_titles_hide (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (GTK_CLIST_SHOW_TITLES (clist))
+  if (GTK_CLIST_SHOW_TITLES(clist))
     {
       GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
       if (clist->title_window)
@@ -1328,6 +1420,9 @@ gtk_clist_column_titles_active (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
+  if (!GTK_CLIST_SHOW_TITLES(clist))
+    return;
+
   for (i = 0; i < clist->columns; i++)
     gtk_clist_column_title_active (clist, i);
 }
@@ -1340,7 +1435,7 @@ gtk_clist_column_titles_passive (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (!GTK_CLIST_SHOW_TITLES (clist))
+  if (!GTK_CLIST_SHOW_TITLES(clist))
     return;
 
   for (i = 0; i < clist->columns; i++)
@@ -1608,7 +1703,7 @@ gtk_clist_set_column_auto_resize (GtkCList *clist,
   if (auto_resize)
     {
       clist->column[column].resizeable = FALSE;
-      if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
        {
          gint width;
 
@@ -1658,7 +1753,7 @@ gtk_clist_optimal_column_width (GtkCList *clist,
   if (column < 0 || column > clist->columns)
     return 0;
 
-  if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
+  if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
     width = (clist->column[column].button->requisition.width -
             (CELL_SPACING + (2 * COLUMN_INSET)));
   else
@@ -1756,7 +1851,7 @@ column_auto_resize (GtkCList    *clist,
   GtkRequisition requisition;
 
   if (!clist->column[column].auto_resize ||
-      GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     return;
 
   if (clist_row)
@@ -1775,7 +1870,7 @@ column_auto_resize (GtkCList    *clist,
 
       /* run a "gtk_clist_optimal_column_width" but break, if
        * the column doesn't shrink */
-      if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
+      if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
        new_width = (clist->column[column].button->requisition.width -
                     (CELL_SPACING + (2 * COLUMN_INSET)));
       else
@@ -1831,7 +1926,7 @@ abort_column_resize (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (!GTK_CLIST_IN_DRAG (clist))
+  if (!GTK_CLIST_IN_DRAG(clist))
     return;
 
   GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
@@ -1842,7 +1937,7 @@ abort_column_resize (GtkCList *clist)
   if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
     draw_xor_line (clist);
 
-  if (GTK_CLIST_ADD_MODE (clist))
+  if (GTK_CLIST_ADD_MODE(clist))
     {
       gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
       gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
@@ -1947,7 +2042,7 @@ size_allocate_columns (GtkCList *clist,
       clist->column[i].area.x = xoffset;
       if (clist->column[i].width_set)
        {
-         if (!block_resize && GTK_CLIST_SHOW_TITLES (clist) &&
+         if (!block_resize && GTK_CLIST_SHOW_TITLES(clist) &&
              clist->column[i].auto_resize && clist->column[i].button)
            {
              gint width;
@@ -1962,7 +2057,7 @@ size_allocate_columns (GtkCList *clist,
          clist->column[i].area.width = clist->column[i].width;
          xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET);
        }
-      else if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button)
+      else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
        {
          clist->column[i].area.width =
            clist->column[i].button->requisition.width -
@@ -1991,7 +2086,7 @@ list_requisition_width (GtkCList *clist)
 
       if (clist->column[i].width_set)
        width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
-      else if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button)
+      else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
        width += clist->column[i].button->requisition.width;
     }
 
@@ -2107,7 +2202,7 @@ gtk_clist_set_row_height (GtkCList *clist,
 
   if (GTK_WIDGET_REALIZED (clist))
     {
-      if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
+      if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
        {
          clist->row_height = (widget->style->font->ascent +
                               widget->style->font->descent + 1);
@@ -2407,7 +2502,7 @@ gtk_clist_set_shift (GtkCList *clist,
   clist_row = (g_list_nth (clist->row_list, row))->data;
 
   if (clist->column[column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
                                                   column, &requisition);
 
@@ -2441,7 +2536,7 @@ set_cell_contents (GtkCList    *clist,
   g_return_if_fail (clist_row != NULL);
 
   if (clist->column[column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
                                                   column, &requisition);
 
@@ -2505,7 +2600,7 @@ set_cell_contents (GtkCList    *clist,
     }
 
   if (clist->column[column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     column_auto_resize (clist, clist_row, column, requisition.width);
 }
 
@@ -2659,7 +2754,7 @@ real_insert_row (GtkCList *clist,
     }
   else
     {
-      if (GTK_CLIST_AUTO_SORT (clist))   /* override insertion pos */
+      if (GTK_CLIST_AUTO_SORT(clist))   /* override insertion pos */
        {
          GList *work;
          
@@ -2819,7 +2914,7 @@ real_clear (GtkCList *clist)
   for (i = 0; i < clist->columns; i++)
     if (clist->column[i].auto_resize)
       {
-       if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button)
+       if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
          gtk_clist_set_column_width
            (clist, i, (clist->column[i].button->requisition.width -
                        (CELL_SPACING + (2 * COLUMN_INSET))));
@@ -2849,7 +2944,7 @@ real_row_move (GtkCList *clist,
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CLIST_AUTO_SORT(clist))
     return;
 
   if (source_row < 0 || source_row >= clist->rows ||
@@ -2985,7 +3080,7 @@ gtk_clist_swap_rows (GtkCList *clist,
   g_return_if_fail (GTK_IS_CLIST (clist));
   g_return_if_fail (row1 != row2);
 
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CLIST_AUTO_SORT(clist))
     return;
 
   gtk_clist_freeze (clist);
@@ -3007,7 +3102,7 @@ gtk_clist_row_move (GtkCList *clist,
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CLIST_AUTO_SORT(clist))
     return;
 
   if (source_row < 0 || source_row >= clist->rows ||
@@ -3139,7 +3234,7 @@ gtk_clist_set_cell_style (GtkCList *clist,
     return;
 
   if (clist->column[column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
                                                   column, &requisition);
 
@@ -3213,7 +3308,7 @@ gtk_clist_set_row_style (GtkCList *clist,
 
   old_width = g_new (gint, clist->columns);
 
-  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     {
       for (i = 0; i < clist->columns; i++)
        if (clist->column[i].auto_resize)
@@ -3242,7 +3337,7 @@ gtk_clist_set_row_style (GtkCList *clist,
                                             clist->clist_window);
     }
 
-  if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+  if (GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     for (i = 0; i < clist->columns; i++)
       column_auto_resize (clist, clist_row, i, old_width[i]);
 
@@ -3307,22 +3402,8 @@ gtk_clist_set_selectable (GtkCList *clist,
       if (clist->anchor >= 0 &&
          clist->selection_mode == GTK_SELECTION_EXTENDED)
        {
-         if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
-           {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gtk_grab_remove (GTK_WIDGET (clist));
-             gdk_pointer_ungrab (GDK_CURRENT_TIME);
-             if (clist->htimer)
-               {
-                 gtk_timeout_remove (clist->htimer);
-                 clist->htimer = 0;
-               }
-             if (clist->vtimer)
-               {
-                 gtk_timeout_remove (clist->vtimer);
-                 clist->vtimer = 0;
-               }
-           }
+         clist->drag_button = 0;
+         remove_grab (clist);
          GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
        }
       gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
@@ -3513,7 +3594,7 @@ toggle_focus_row (GtkCList *clist)
       clist->drag_pos = clist->focus_row;
       clist->undo_anchor = clist->focus_row;
       
-      if (GTK_CLIST_ADD_MODE (clist))
+      if (GTK_CLIST_ADD_MODE(clist))
        fake_toggle_row (clist, clist->focus_row);
       else
        GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
@@ -3536,7 +3617,7 @@ toggle_add_mode (GtkCList *clist)
     return;
 
   gtk_clist_draw_focus (GTK_WIDGET (clist));
-  if (!GTK_CLIST_ADD_MODE (clist))
+  if (!GTK_CLIST_ADD_MODE(clist))
     {
       GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
       gdk_gc_set_line_attributes (clist->xor_gc, 1,
@@ -3814,7 +3895,7 @@ real_undo_selection (GtkCList *clist)
     gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
                     GPOINTER_TO_INT (work->data), -1, NULL);
 
-  if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
+  if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
     {
       gtk_clist_draw_focus (GTK_WIDGET (clist));
       clist->focus_row = clist->undo_anchor;
@@ -4109,7 +4190,7 @@ start_selection (GtkCList *clist)
   if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
     return;
 
-  set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
+  set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
              clist->focus_row);
 }
 
@@ -4119,7 +4200,7 @@ end_selection (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)) ||
+  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS(clist)) ||
       clist->anchor == -1)
     return;
   
@@ -4140,7 +4221,7 @@ extend_selection (GtkCList      *clist,
     return;
 
   if (auto_start_selection)
-    set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
+    set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
                clist->focus_row);
   else if (clist->anchor == -1)
     return;
@@ -4243,16 +4324,7 @@ gtk_clist_destroy (GtkObject *object)
       clist->vadjustment = NULL;
     }
 
-  if (clist->htimer)
-    {
-      gtk_timeout_remove (clist->htimer);
-      clist->htimer = 0;
-    }
-  if (clist->vtimer)
-    {
-      gtk_timeout_remove (clist->vtimer);
-      clist->vtimer = 0;
-    }
+  remove_grab (clist);
 
   /* destroy the column buttons */
   for (i = 0; i < clist->columns; i++)
@@ -4700,7 +4772,7 @@ gtk_clist_style_set (GtkWidget *widget,
   /* Fill in data after widget has correct style */
 
   /* text properties */
-  if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
+  if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
     {
       clist->row_height = (widget->style->font->ascent +
                           widget->style->font->descent + 1);
@@ -4712,7 +4784,7 @@ gtk_clist_style_set (GtkWidget *widget,
                                      widget->style->font->descent - 1) / 2;
 
   /* Column widths */
-  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     {
       gint width;
       gint i;
@@ -4765,6 +4837,7 @@ gtk_clist_button_press (GtkWidget      *widget,
   gint y;
   gint row;
   gint column;
+  gint button_actions;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
@@ -4772,10 +4845,11 @@ gtk_clist_button_press (GtkWidget      *widget,
 
   clist = GTK_CLIST (widget);
 
-  /* we don't handle button 2 and 3 */
-  if (event->button != 1)
+  button_actions = clist->button_actions[event->button - 1];
+
+  if (button_actions == GTK_BUTTON_IGNORED)
     return FALSE;
-  
+
   /* selections on the list */
   if (event->window == clist->clist_window)
     {
@@ -4791,123 +4865,141 @@ gtk_clist_button_press (GtkWidget      *widget,
 
          if (event->type == GDK_BUTTON_PRESS)
            {
-             GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gdk_pointer_grab (clist->clist_window, FALSE,
-                               GDK_POINTER_MOTION_HINT_MASK |
-                               GDK_BUTTON1_MOTION_MASK |
-                               GDK_BUTTON_RELEASE_MASK,
+             GdkEventMask mask = ((1 << (4 + event->button)) |
+                                  GDK_POINTER_MOTION_HINT_MASK |
+                                  GDK_BUTTON_RELEASE_MASK);
+
+             clist->click_cell.row = row;
+             clist->click_cell.column = column;
+                 
+             clist->drag_button = event->button;
+             gdk_pointer_grab (clist->clist_window, FALSE, mask,
                                NULL, NULL, event->time);
              gtk_grab_add (widget);
            }
-         else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (widget))
+         else
            {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gtk_grab_remove (widget);
-             gdk_pointer_ungrab (event->time);
+             if (clist->drag_button == 0)
+               return FALSE;
+
+             clist->click_cell.row = -1;
+             clist->click_cell.column = -1;
+
+             clist->drag_button = 0;
+             remove_grab (clist);
            }
 
-         if (GTK_CLIST_ADD_MODE (clist))
+         if (button_actions & GTK_BUTTON_SELECTS)
            {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
-             if (GTK_WIDGET_HAS_FOCUS (widget))
-               {
-                 gtk_clist_draw_focus (widget);
-                 gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                             GDK_LINE_SOLID, 0, 0);
-                 clist->focus_row = row;
-                 gtk_clist_draw_focus (widget);
-               }
-             else
+             if (GTK_CLIST_ADD_MODE(clist))
                {
-                 gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                             GDK_LINE_SOLID, 0, 0);
-                 clist->focus_row = row;
+                 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
+                 if (GTK_WIDGET_HAS_FOCUS(widget))
+                   {
+                     gtk_clist_draw_focus (widget);
+                     gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                                 GDK_LINE_SOLID, 0, 0);
+                     clist->focus_row = row;
+                     gtk_clist_draw_focus (widget);
+                   }
+                 else
+                   {
+                     gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                                 GDK_LINE_SOLID, 0, 0);
+                     clist->focus_row = row;
+                   }
                }
-           }
-         else if (row != clist->focus_row)
-           {
-             if (GTK_WIDGET_HAS_FOCUS (widget))
+             else if (row != clist->focus_row)
                {
-                 gtk_clist_draw_focus (widget);
-                 clist->focus_row = row;
-                 gtk_clist_draw_focus (widget);
+                 if (GTK_WIDGET_HAS_FOCUS(widget))
+                   {
+                     gtk_clist_draw_focus (widget);
+                     clist->focus_row = row;
+                     gtk_clist_draw_focus (widget);
+                   }
+                 else
+                   clist->focus_row = row;
                }
-             else
-               clist->focus_row = row;
            }
 
-         if (!GTK_WIDGET_HAS_FOCUS (widget))
+         if (!GTK_WIDGET_HAS_FOCUS(widget))
            gtk_widget_grab_focus (widget);
 
-         switch (clist->selection_mode)
+         if (button_actions & GTK_BUTTON_SELECTS)
            {
-           case GTK_SELECTION_SINGLE:
-           case GTK_SELECTION_MULTIPLE:
-             if (event->type != GDK_BUTTON_PRESS)
-               gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
-                                row, column, event);
-             else
-               clist->anchor = row;
-             break;
-           case GTK_SELECTION_BROWSE:
-             gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
-                              row, column, event);
-             break;
-           case GTK_SELECTION_EXTENDED:
-             if (event->type != GDK_BUTTON_PRESS)
+             switch (clist->selection_mode)
                {
-                 if (clist->anchor != -1)
-                   {
-                     update_extended_selection (clist, clist->focus_row);
-                     GTK_CLIST_CLASS_FW (clist)->resync_selection
-                       (clist, (GdkEvent *) event);
-                   }
+               case GTK_SELECTION_SINGLE:
+               case GTK_SELECTION_MULTIPLE:
+                 if (event->type != GDK_BUTTON_PRESS)
+                   gtk_signal_emit (GTK_OBJECT (clist),
+                                    clist_signals[SELECT_ROW],
+                                    row, column, event);
+                 else
+                   clist->anchor = row;
+                 break;
+               case GTK_SELECTION_BROWSE:
                  gtk_signal_emit (GTK_OBJECT (clist),
                                   clist_signals[SELECT_ROW],
                                   row, column, event);
                  break;
-               }
-             
-             if (event->state & GDK_CONTROL_MASK)
-               {
-                 if (event->state & GDK_SHIFT_MASK)
+               case GTK_SELECTION_EXTENDED:
+                 if (event->type != GDK_BUTTON_PRESS)
                    {
-                     if (clist->anchor < 0)
+                     if (clist->anchor != -1)
                        {
-                         g_list_free (clist->undo_selection);
-                         g_list_free (clist->undo_unselection);
-                         clist->undo_selection = NULL;
-                         clist->undo_unselection = NULL;
-                         clist->anchor = old_row;
-                         clist->drag_pos = old_row;
-                         clist->undo_anchor = old_row;
+                         update_extended_selection (clist, clist->focus_row);
+                         GTK_CLIST_CLASS_FW (clist)->resync_selection
+                           (clist, (GdkEvent *) event);
                        }
-                     update_extended_selection (clist, clist->focus_row);
+                     gtk_signal_emit (GTK_OBJECT (clist),
+                                      clist_signals[SELECT_ROW],
+                                      row, column, event);
+                     break;
                    }
-                 else
+             
+                 if (event->state & GDK_CONTROL_MASK)
                    {
-                     if (clist->anchor == -1)
-                       set_anchor (clist, TRUE, row, old_row);
+                     if (event->state & GDK_SHIFT_MASK)
+                       {
+                         if (clist->anchor < 0)
+                           {
+                             g_list_free (clist->undo_selection);
+                             g_list_free (clist->undo_unselection);
+                             clist->undo_selection = NULL;
+                             clist->undo_unselection = NULL;
+                             clist->anchor = old_row;
+                             clist->drag_pos = old_row;
+                             clist->undo_anchor = old_row;
+                           }
+                         update_extended_selection (clist, clist->focus_row);
+                       }
                      else
-                       update_extended_selection (clist, clist->focus_row);
+                       {
+                         if (clist->anchor == -1)
+                           set_anchor (clist, TRUE, row, old_row);
+                         else
+                           update_extended_selection (clist,
+                                                      clist->focus_row);
+                       }
+                     break;
                    }
-                 break;
-               }
 
-             if (event->state & GDK_SHIFT_MASK)
-               {
-                 set_anchor (clist, FALSE, old_row, old_row);
-                 update_extended_selection (clist, clist->focus_row);
+                 if (event->state & GDK_SHIFT_MASK)
+                   {
+                     set_anchor (clist, FALSE, old_row, old_row);
+                     update_extended_selection (clist, clist->focus_row);
+                     break;
+                   }
+
+                 if (clist->anchor == -1)
+                   set_anchor (clist, FALSE, row, old_row);
+                 else
+                   update_extended_selection (clist, clist->focus_row);
+                 break;
+               default:
                  break;
                }
-
-             if (clist->anchor == -1)
-               set_anchor (clist, FALSE, row, old_row);
-             else
-               update_extended_selection (clist, clist->focus_row);
-             break;
-           default:
-             break;
            }
        }
 
@@ -4927,14 +5019,14 @@ gtk_clist_button_press (GtkWidget      *widget,
        gtk_grab_add (widget);
        GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
 
-       if (!GTK_WIDGET_HAS_FOCUS (widget))
+       if (!GTK_WIDGET_HAS_FOCUS(widget))
          gtk_widget_grab_focus (widget);
 
        clist->drag_pos = i;
        clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
                         clist->column[i].area.width + CELL_SPACING);
 
-       if (GTK_CLIST_ADD_MODE (clist))
+       if (GTK_CLIST_ADD_MODE(clist))
          gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
        draw_xor_line (clist);
 
@@ -4948,6 +5040,7 @@ gtk_clist_button_release (GtkWidget      *widget,
                          GdkEventButton *event)
 {
   GtkCList *clist;
+  gint button_actions;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
@@ -4955,12 +5048,12 @@ gtk_clist_button_release (GtkWidget      *widget,
 
   clist = GTK_CLIST (widget);
 
-  /* we don't handle button 2 and 3 */
-  if (event->button != 1)
+  button_actions = clist->button_actions[event->button - 1];
+  if (button_actions == GTK_BUTTON_IGNORED)
     return FALSE;
 
   /* release on resize windows */
-  if (GTK_CLIST_IN_DRAG (clist))
+  if (GTK_CLIST_IN_DRAG(clist))
     {
       gint width;
       gint x;
@@ -4977,7 +5070,7 @@ gtk_clist_button_release (GtkWidget      *widget,
       if (clist->x_drag >= 0)
        draw_xor_line (clist);
 
-      if (GTK_CLIST_ADD_MODE (clist))
+      if (GTK_CLIST_ADD_MODE(clist))
        {
          gdk_gc_set_line_attributes (clist->xor_gc, 1,
                                      GDK_LINE_ON_OFF_DASH, 0, 0);
@@ -4989,134 +5082,46 @@ gtk_clist_button_release (GtkWidget      *widget,
       return FALSE;
     }
 
-  if (GTK_CLIST_DRAG_SELECTION (clist))
+  if (clist->drag_button)
     {
       gint row;
       gint column;
 
-      GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-      gtk_grab_remove (widget);
-      gdk_pointer_ungrab (event->time);
-      if (clist->htimer)
-       {
-         gtk_timeout_remove (clist->htimer);
-         clist->htimer = 0;
-       }
-      if (clist->vtimer)
-       {
-         gtk_timeout_remove (clist->vtimer);
-         clist->vtimer = 0;
-       }
-      switch (clist->selection_mode)
-       {
-       case GTK_SELECTION_EXTENDED:
-         if (!(event->state & GDK_SHIFT_MASK) ||
-             event->x < 0 || event->x >= clist->clist_window_width ||
-             event->y < 0 || event->y >= clist->clist_window_height)
-           GTK_CLIST_CLASS_FW (clist)->resync_selection
-             (clist, (GdkEvent *) event);
-         break;
+      clist->drag_button = 0;
+      clist->click_cell.row = -1;
+      clist->click_cell.column = -1;
 
-       case GTK_SELECTION_SINGLE:
-       case GTK_SELECTION_MULTIPLE:
-         if (get_selection_info (clist, event->x, event->y, &row, &column))
+      remove_grab (clist);
+
+      if (button_actions & GTK_BUTTON_SELECTS)
+       {
+         switch (clist->selection_mode)
            {
-             if (row >= 0 && row < clist->rows && clist->anchor == row)
-               toggle_row (clist, row, column, (GdkEvent *) event);
+           case GTK_SELECTION_EXTENDED:
+             if (!(event->state & GDK_SHIFT_MASK) ||
+                 event->x < 0 || event->x >= clist->clist_window_width ||
+                 event->y < 0 || event->y >= clist->clist_window_height)
+               GTK_CLIST_CLASS_FW (clist)->resync_selection
+                 (clist, (GdkEvent *) event);
+             break;
+           case GTK_SELECTION_SINGLE:
+           case GTK_SELECTION_MULTIPLE:
+             if (get_selection_info (clist, event->x, event->y,
+                                     &row, &column))
+               {
+                 if (row >= 0 && row < clist->rows && clist->anchor == row)
+                   toggle_row (clist, row, column, (GdkEvent *) event);
+               }
+             clist->anchor = -1;
+             break;
+           default:
+             break;
            }
-         clist->anchor = -1;
-         break;
-
-       default:
-         break;
        }
     }
-
-  return FALSE;
-}
-
-static gint
-horizontal_timeout (GtkCList *clist)
-{
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
-
-  GTK_THREADS_ENTER;
-
-  clist->htimer = 0;
-  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
-
-  event.is_hint = 0;
-  event.x = x;
-  event.y = y;
-  event.state = mask;
-
-  gtk_clist_motion (GTK_WIDGET (clist), &event);
-
-  GTK_THREADS_LEAVE;
-  
-  return FALSE;
-}
-
-static gint
-vertical_timeout (GtkCList *clist)
-{
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
-
-  GTK_THREADS_ENTER;
-
-  clist->vtimer = 0;
-  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
-
-  event.is_hint = 0;
-  event.x = x;
-  event.y = y;
-  event.state = mask;
-
-  gtk_clist_motion (GTK_WIDGET (clist), &event);
-
-  GTK_THREADS_LEAVE;
-
   return FALSE;
 }
 
-static void
-move_vertical (GtkCList *clist,
-              gint      row,
-              gfloat    align)
-{
-  gfloat value;
-
-  if (!clist->vadjustment)
-    return;
-
-  value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
-          align * (clist->clist_window_height - clist->row_height) +
-          (2 * align - 1) * CELL_SPACING);
-
-  if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
-    value = clist->vadjustment->upper - clist->vadjustment->page_size;
-
-  gtk_adjustment_set_value(clist->vadjustment, value);
-}
-
-static void
-move_horizontal (GtkCList *clist,
-                gint      diff)
-{
-  gfloat value;
-
-  if (!clist->hadjustment)
-    return;
-
-  value = CLAMP (clist->hadjustment->value + diff, 0.0,
-                clist->hadjustment->upper - clist->hadjustment->page_size);
-  gtk_adjustment_set_value(clist->hadjustment, value);
-}
-
 static gint
 gtk_clist_motion (GtkWidget      *widget,
                  GdkEventMotion *event)
@@ -5126,6 +5131,7 @@ gtk_clist_motion (GtkWidget      *widget,
   gint y;
   gint row;
   gint new_width;
+  gint button_actions;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
@@ -5134,7 +5140,9 @@ gtk_clist_motion (GtkWidget      *widget,
   if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
     return FALSE;
 
-  if (GTK_CLIST_IN_DRAG (clist))
+  button_actions = clist->button_actions[clist->drag_button - 1];
+
+  if (GTK_CLIST_IN_DRAG(clist))
     {
       if (event->is_hint || event->window != widget->window)
        gtk_widget_get_pointer (widget, &x, NULL);
@@ -5177,6 +5185,49 @@ gtk_clist_motion (GtkWidget      *widget,
   if (event->is_hint || event->window != clist->clist_window)
     gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
 
+  if (GTK_CLIST_REORDERABLE(clist) && button_actions & GTK_BUTTON_DRAGS)
+    {
+      /* delayed drag start */
+      if (clist->click_cell.row >= 0 && clist->click_cell.column >= 0 &&
+         (y < 0 || y >= clist->clist_window_height ||
+          x < 0 || x >= clist->clist_window_width  ||
+          y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) ||
+          y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) +
+                clist->row_height) ||
+          x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) ||
+          x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) + 
+                clist->column[clist->click_cell.column].area.width)))
+       {
+         GdkDragContext *context;
+         GtkTargetList  *target_list;
+         gint button;
+
+         button = clist->drag_button;
+         clist->drag_button = 0;
+         remove_grab (clist);
+
+         switch (clist->selection_mode)
+           {
+           case GTK_SELECTION_EXTENDED:
+             update_extended_selection (clist, clist->focus_row);
+             GTK_CLIST_CLASS_FW (clist)->resync_selection
+               (clist, (GdkEvent *) event);
+             break;
+           case GTK_SELECTION_SINGLE:
+           case GTK_SELECTION_MULTIPLE:
+             clist->anchor = -1;
+           case GTK_SELECTION_BROWSE:
+             break;
+           }
+
+         target_list = gtk_target_list_new (&clist_target_table, 1);
+         context = gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE,
+                                   button, (GdkEvent *)event);
+
+       }
+      return TRUE;
+    }
+
   /* horizontal autoscrolling */
   if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width &&
       (x < 0 || x >= clist->clist_window_width))
@@ -5199,7 +5250,7 @@ gtk_clist_motion (GtkWidget      *widget,
        }
     }
 
-  if (GTK_CLIST_IN_DRAG (clist))
+  if (GTK_CLIST_IN_DRAG(clist))
     return FALSE;
 
   /* vertical autoscrolling */
@@ -5219,18 +5270,16 @@ gtk_clist_motion (GtkWidget      *widget,
       clist->vtimer = gtk_timeout_add (SCROLL_TIME,
                                       (GtkFunction) vertical_timeout, clist);
 
-      if (GTK_CLIST_DRAG_SELECTION (clist))
-       {
-         if ((y < 0 && clist->focus_row == 0) ||
-             (y >= clist->clist_window_height &&
-              clist->focus_row == clist->rows-1))
-           return FALSE;
-       }
+      if (clist->drag_button &&
+         ((y < 0 && clist->focus_row == 0) ||
+          (y >= clist->clist_window_height &&
+           clist->focus_row == clist->rows - 1)))
+       return FALSE;
     }
 
   row = CLAMP (row, 0, clist->rows - 1);
 
-  if (GTK_CLIST_DRAG_SELECTION (clist))
+  if (button_actions & GTK_BUTTON_SELECTS)
     {
       if (row == clist->focus_row)
        return FALSE;
@@ -5280,7 +5329,7 @@ gtk_clist_size_request (GtkWidget      *widget,
 
   /* compute the size of the column title (title) area */
   clist->column_title_area.height = 0;
-  if (GTK_CLIST_SHOW_TITLES (clist))
+  if (GTK_CLIST_SHOW_TITLES(clist))
     for (i = 0; i < clist->columns; i++)
       if (clist->column[i].button)
        {
@@ -5772,7 +5821,7 @@ draw_row (GtkCList     *clist,
     }
 
   /* draw focus rectangle */
-  if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
+  if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS(widget))
     {
       if (!area)
        gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
@@ -5922,10 +5971,7 @@ gtk_clist_get_selection_info (GtkCList *clist,
   return get_selection_info (clist, x, y, row, column);
 }
 
-/* 
- * SCROLLBARS
- *
- * functions:
+/* PRIVATE ADJUSTMENT FUNCTIONS
  *   adjust_adjustments
  *   vadjustment_changed
  *   hadjustment_changed
@@ -6145,8 +6191,8 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
          return;
        }
 
-      if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         GTK_CLIST_ADD_MODE (clist))
+      if (GTK_WIDGET_HAS_FOCUS(clist) && !GTK_CLIST_CHILD_HAS_FOCUS(clist) &&
+         GTK_CLIST_ADD_MODE(clist))
        {
          y = ROW_TOP_YPIXEL (clist, clist->focus_row);
              
@@ -6180,8 +6226,8 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
          return;
        }
       
-      if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         GTK_CLIST_ADD_MODE (clist))
+      if (GTK_WIDGET_HAS_FOCUS(clist) && !GTK_CLIST_CHILD_HAS_FOCUS(clist) &&
+         GTK_CLIST_ADD_MODE(clist))
        {
          y = ROW_TOP_YPIXEL (clist, clist->focus_row);
          
@@ -6208,9 +6254,9 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
 
   check_exposures (clist);
 
-  if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist))
+  if (GTK_WIDGET_HAS_FOCUS(clist) && !GTK_CLIST_CHILD_HAS_FOCUS(clist))
     {
-      if (GTK_CLIST_ADD_MODE (clist))
+      if (GTK_CLIST_ADD_MODE(clist))
        {
          gint focus_row;
          
@@ -6273,7 +6319,7 @@ check_exposures (GtkCList *clist)
     }
 }
 
-/* 
+/* PRIVATE 
  * Memory Allocation/Distruction Routines for GtkCList stuctures
  *
  * functions:
@@ -6426,7 +6472,7 @@ gtk_clist_focus (GtkContainer     *container,
     {
     case GTK_DIR_LEFT:
     case GTK_DIR_RIGHT:
-      if (GTK_CLIST_CHILD_HAS_FOCUS (clist))
+      if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
        {
          if (title_focus (clist, direction))
            return TRUE;
@@ -6437,7 +6483,7 @@ gtk_clist_focus (GtkContainer     *container,
       return TRUE;
     case GTK_DIR_DOWN:
     case GTK_DIR_TAB_FORWARD:
-      if (GTK_CLIST_CHILD_HAS_FOCUS (clist))
+      if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
        {
          gboolean tf = FALSE;
 
@@ -6469,7 +6515,7 @@ gtk_clist_focus (GtkContainer     *container,
     case GTK_DIR_UP:
     case GTK_DIR_TAB_BACKWARD:
       if (!focus_child &&
-         GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows)
+         GTK_CLIST_CHILD_HAS_FOCUS(clist) && clist->rows)
        {
          if (clist->focus_row < 0)
            {
@@ -6600,7 +6646,7 @@ title_focus (GtkCList *clist,
   gint i = 0;
   gint j;
 
-  if (!GTK_CLIST_SHOW_TITLES (clist))
+  if (!GTK_CLIST_SHOW_TITLES(clist))
     return FALSE;
 
   focus_child = GTK_CONTAINER (clist)->focus_child;
@@ -6609,7 +6655,7 @@ title_focus (GtkCList *clist,
     {
     case GTK_DIR_TAB_BACKWARD:
     case GTK_DIR_UP:
-      if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS (clist))
+      if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS(clist))
        {
          if (dir == GTK_DIR_UP)
            i = COLUMN_FROM_XPIXEL (clist, 0);
@@ -6646,7 +6692,7 @@ title_focus (GtkCList *clist,
            if (clist->column[i].button && 
                GTK_WIDGET_VISIBLE (clist->column[i].button) &&
                GTK_IS_CONTAINER (clist->column[i].button) &&
-               !GTK_WIDGET_HAS_FOCUS (clist->column[i].button))
+               !GTK_WIDGET_HAS_FOCUS(clist->column[i].button))
              if (gtk_container_focus 
                  (GTK_CONTAINER (clist->column[i].button), dir))
                {
@@ -6702,10 +6748,15 @@ title_focus (GtkCList *clist,
   return return_val;
 }
 
-/* SCROLLING FUNCTIONS
+/* PRIVATE SCROLLING FUNCTIONS
  *   move_focus_row
  *   scroll_horizontal
  *   scroll_vertical
+ *   move_horizontal
+ *   move_vertical
+ *   horizontal_timeout
+ *   vertical_timeout
+ *   remove_grab
  */
 static void
 move_focus_row (GtkCList      *clist,
@@ -6852,7 +6903,7 @@ scroll_vertical (GtkCList      *clist,
          if (clist->selection_mode == GTK_SELECTION_BROWSE)
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
                             old_focus_row, -1, NULL);
-         else if (!GTK_CLIST_ADD_MODE (clist))
+         else if (!GTK_CLIST_ADD_MODE(clist))
            {
              gtk_clist_unselect_all (clist);
              clist->undo_anchor = old_focus_row;
@@ -6864,7 +6915,7 @@ scroll_vertical (GtkCList      *clist,
        case GTK_VISIBILITY_NONE:
          if (old_focus_row != clist->focus_row &&
              !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
-               GTK_CLIST_ADD_MODE (clist)))
+               GTK_CLIST_ADD_MODE(clist)))
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
                             clist->focus_row, -1, NULL);
          switch (scroll_type)
@@ -6904,7 +6955,7 @@ scroll_vertical (GtkCList      *clist,
        default:
          if (old_focus_row != clist->focus_row &&
              !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
-               GTK_CLIST_ADD_MODE (clist)))
+               GTK_CLIST_ADD_MODE(clist)))
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
                             clist->focus_row, -1, NULL);
          break;
@@ -6922,25 +6973,129 @@ scroll_vertical (GtkCList      *clist,
     }
 }
 
-/* PUBLIC SORTING FUNCTIONS
- * gtk_clist_sort
- * gtk_clist_set_compare_func
- * gtk_clist_set_auto_sort
- * gtk_clist_set_sort_type
- * gtk_clist_set_sort_column
- */
-void
-gtk_clist_sort (GtkCList *clist)
+static void
+move_horizontal (GtkCList *clist,
+                gint      diff)
 {
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  gfloat value;
 
-  GTK_CLIST_CLASS_FW (clist)->sort_list (clist);
+  if (!clist->hadjustment)
+    return;
+
+  value = CLAMP (clist->hadjustment->value + diff, 0.0,
+                clist->hadjustment->upper - clist->hadjustment->page_size);
+  gtk_adjustment_set_value(clist->hadjustment, value);
 }
 
-void
-gtk_clist_set_compare_func (GtkCList            *clist,
-                           GtkCListCompareFunc  cmp_func)
+static void
+move_vertical (GtkCList *clist,
+              gint      row,
+              gfloat    align)
+{
+  gfloat value;
+
+  if (!clist->vadjustment)
+    return;
+
+  value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
+          align * (clist->clist_window_height - clist->row_height) +
+          (2 * align - 1) * CELL_SPACING);
+
+  if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
+    value = clist->vadjustment->upper - clist->vadjustment->page_size;
+
+  gtk_adjustment_set_value(clist->vadjustment, value);
+}
+
+static gint
+horizontal_timeout (GtkCList *clist)
+{
+  gint x, y;
+  GdkEventMotion event;
+  GdkModifierType mask;
+
+  GTK_THREADS_ENTER;
+
+  clist->htimer = 0;
+  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
+
+  event.is_hint = 0;
+  event.x = x;
+  event.y = y;
+  event.state = mask;
+
+  gtk_clist_motion (GTK_WIDGET (clist), &event);
+
+  GTK_THREADS_LEAVE;
+  
+  return FALSE;
+}
+
+static gint
+vertical_timeout (GtkCList *clist)
+{
+  gint x, y;
+  GdkEventMotion event;
+  GdkModifierType mask;
+
+  GTK_THREADS_ENTER;
+
+  clist->vtimer = 0;
+  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
+
+  event.is_hint = 0;
+  event.x = x;
+  event.y = y;
+  event.state = mask;
+
+  gtk_clist_motion (GTK_WIDGET (clist), &event);
+
+  GTK_THREADS_LEAVE;
+
+  return FALSE;
+}
+
+static void
+remove_grab (GtkCList *clist)
+{
+  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+    {
+      gtk_grab_remove (GTK_WIDGET (clist));
+      gdk_pointer_ungrab (GDK_CURRENT_TIME);
+    }
+
+  if (clist->htimer)
+    {
+      gtk_timeout_remove (clist->htimer);
+      clist->htimer = 0;
+    }
+
+  if (clist->vtimer)
+    {
+      gtk_timeout_remove (clist->vtimer);
+      clist->vtimer = 0;
+    }
+}
+
+/* PUBLIC SORTING FUNCTIONS
+ * gtk_clist_sort
+ * gtk_clist_set_compare_func
+ * gtk_clist_set_auto_sort
+ * gtk_clist_set_sort_type
+ * gtk_clist_set_sort_column
+ */
+void
+gtk_clist_sort (GtkCList *clist)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  GTK_CLIST_CLASS_FW (clist)->sort_list (clist);
+}
+
+void
+gtk_clist_set_compare_func (GtkCList            *clist,
+                           GtkCListCompareFunc  cmp_func)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -6955,9 +7110,9 @@ gtk_clist_set_auto_sort (GtkCList *clist,
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
   
-  if (GTK_CLIST_AUTO_SORT (clist) && !auto_sort)
+  if (GTK_CLIST_AUTO_SORT(clist) && !auto_sort)
     GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
-  else if (!GTK_CLIST_AUTO_SORT (clist) && auto_sort)
+  else if (!GTK_CLIST_AUTO_SORT(clist) && auto_sort)
     {
       GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
       gtk_clist_sort (clist);
@@ -7166,3 +7321,454 @@ gtk_clist_mergesort (GtkCList *clist,
                       gtk_clist_mergesort (clist, half, num - num / 2));
     }
 }
+
+/************************/
+
+static void
+drag_source_info_destroy (gpointer data)
+{
+  GtkCListCellInfo *info = data;
+
+  g_free (info);
+}
+
+static void
+drag_dest_info_destroy (gpointer data)
+{
+  GtkCListDestInfo *info = data;
+
+  g_free (info);
+}
+
+static void
+gtk_clist_drag_begin (GtkWidget             *widget,
+                     GdkDragContext *context)
+{
+  GtkCList *clist;
+  GtkCListCellInfo *info;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CLIST (widget);
+
+  info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+  if (!info)
+    {
+      info = g_new (GtkCListCellInfo, 1);
+
+      if (clist->click_cell.row < 0)
+       clist->click_cell.row = 0;
+      else if (clist->click_cell.row >= clist->rows)
+       clist->click_cell.row = clist->rows - 1;
+      info->row = clist->click_cell.row;
+      info->column = clist->click_cell.column;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
+                              drag_source_info_destroy);
+    }
+
+  if (GTK_CLIST_USE_DRAG_ICONS (clist))
+    gtk_drag_set_icon_default (context);
+}
+
+static void
+gtk_clist_drag_end (GtkWidget     *widget,
+                   GdkDragContext *context)
+{
+  GtkCList *clist;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CLIST (widget);
+
+  clist->click_cell.row = -1;
+  clist->click_cell.column = -1;
+}
+
+static void
+gtk_clist_drag_leave (GtkWidget      *widget,
+                     GdkDragContext *context,
+                     guint           time)
+{
+  GtkCList *clist;
+  GtkCListDestInfo *dest_info;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CLIST (widget);
+
+  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+  
+  if (dest_info)
+    {
+      if (dest_info->cell.row >= 0 &&
+         GTK_CLIST_REORDERABLE(clist) &&
+         gtk_drag_get_source_widget (context) == widget)
+       {
+         GList *list;
+         GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+         list = context->targets;
+         while (list)
+           {
+             if (atom == GPOINTER_TO_INT (list->data))
+               {
+                 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
+                   (clist,
+                    g_list_nth (clist->row_list, dest_info->cell.row)->data,
+                    dest_info->cell.row, dest_info->insert_pos);
+                 break;
+               }
+             list = list->next;
+           }
+       }
+      g_dataset_remove_data (context, "gtk-clist-drag-dest");
+    }
+}
+
+static gint
+gtk_clist_drag_motion (GtkWidget      *widget,
+                      GdkDragContext *context,
+                      gint            x,
+                      gint            y,
+                      guint           time)
+{
+  GtkCList *clist;
+  gint row, column;
+  GtkCListDestInfo *dest_info;
+  gint h = 0;
+  gint insert_pos = GTK_CLIST_DRAG_NONE;
+  gint y_delta;
+
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+
+  clist = GTK_CLIST (widget);
+
+  y -= (GTK_CONTAINER (widget)->border_width +
+       widget->style->klass->ythickness + clist->column_title_area.height);
+  row = ROW_FROM_YPIXEL (clist, y);
+
+  if (row >= clist->rows)
+    {
+      row = clist->rows - 1;
+      y = ROW_TOP_YPIXEL (clist, row) + clist->row_height;
+    }
+  if (row < -1)
+    row = -1;
+
+  x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness;
+  column = COLUMN_FROM_XPIXEL (clist, x);
+
+  if (row >= 0)
+    {
+      y_delta = y - ROW_TOP_YPIXEL (clist, row);
+      
+      if (GTK_CLIST_DRAW_DRAG_RECT(clist))
+       {
+         insert_pos = GTK_CLIST_DRAG_INTO;
+         h = clist->row_height / 4;
+       }
+      else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
+       {
+         insert_pos = GTK_CLIST_DRAG_BEFORE;
+         h = clist->row_height / 2;
+       }
+
+      if (GTK_CLIST_DRAW_DRAG_LINE(clist))
+       {
+         if (y_delta < h)
+           insert_pos = GTK_CLIST_DRAG_BEFORE;
+         else if (clist->row_height - y_delta < h)
+           insert_pos = GTK_CLIST_DRAG_AFTER;
+       }
+    }
+
+  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+  if (!dest_info)
+    {
+      dest_info = g_new (GtkCListDestInfo, 1);
+
+      dest_info->insert_pos  = GTK_CLIST_DRAG_NONE;
+      dest_info->cell.row    = -1;
+      dest_info->cell.column = -1;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
+                              drag_dest_info_destroy);
+    }
+
+  if (GTK_CLIST_REORDERABLE (clist))
+    {
+      GList *list;
+      GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+      list = context->targets;
+      while (list)
+       {
+         if (atom == GPOINTER_TO_INT (list->data))
+           break;
+         list = list->next;
+       }
+
+      if (list)
+       {
+         if (gtk_drag_get_source_widget (context) != widget ||
+             insert_pos == GTK_CLIST_DRAG_NONE ||
+             row == clist->click_cell.row ||
+             (row == clist->click_cell.row - 1 &&
+              insert_pos == GTK_CLIST_DRAG_AFTER) ||
+             (row == clist->click_cell.row + 1 &&
+              insert_pos == GTK_CLIST_DRAG_BEFORE))
+           {
+             if (dest_info->cell.row < 0)
+               {
+                 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
+                 return FALSE;
+               }
+             return TRUE;
+           }
+               
+         if (row != dest_info->cell.row ||
+             (row == dest_info->cell.row &&
+              dest_info->insert_pos != insert_pos))
+           {
+             if (dest_info->cell.row >= 0)
+               GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
+                 (clist, g_list_nth (clist->row_list,
+                                     dest_info->cell.row)->data,
+                  dest_info->cell.row, dest_info->insert_pos);
+
+             dest_info->insert_pos  = insert_pos;
+             dest_info->cell.row    = row;
+             dest_info->cell.column = column;
+             
+             GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
+               (clist, g_list_nth (clist->row_list,
+                                   dest_info->cell.row)->data,
+                dest_info->cell.row, dest_info->insert_pos);
+
+             gdk_drag_status (context, context->suggested_action, time);
+           }
+         return TRUE;
+       }
+    }
+
+  dest_info->insert_pos  = insert_pos;
+  dest_info->cell.row    = row;
+  dest_info->cell.column = column;
+  return TRUE;
+}
+
+static gboolean
+gtk_clist_drag_drop (GtkWidget      *widget,
+                    GdkDragContext *context,
+                    gint            x,
+                    gint            y,
+                    guint           time)
+{
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  if (GTK_CLIST_REORDERABLE (widget) &&
+      gtk_drag_get_source_widget (context) == widget)
+    {
+      GList *list;
+      GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+      list = context->targets;
+      while (list)
+       {
+         if (atom == GPOINTER_TO_INT (list->data))
+           return TRUE;
+         list = list->next;
+       }
+    }
+  return FALSE;
+}
+
+static void
+gtk_clist_drag_data_received (GtkWidget        *widget,
+                             GdkDragContext   *context,
+                             gint              x,
+                             gint              y,
+                             GtkSelectionData *selection_data,
+                             guint             info,
+                             guint32           time)
+{
+  GtkCList *clist;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (selection_data != NULL);
+
+  clist = GTK_CLIST (widget);
+
+  if (GTK_CLIST_REORDERABLE (clist) &&
+      gtk_drag_get_source_widget (context) == widget &&
+      selection_data->target ==
+      gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
+      selection_data->format == GTK_TYPE_POINTER &&
+      selection_data->length == sizeof (GtkCListCellInfo))
+    {
+      GtkCListCellInfo *source_info;
+      GtkCListDestInfo *dest_info;
+
+      source_info = (GtkCListCellInfo *)(selection_data->data);
+      dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+      if (dest_info && source_info)
+       {
+         if (dest_info->insert_pos == GTK_CLIST_DRAG_AFTER)
+           dest_info->cell.row++;
+         if (source_info->row < dest_info->cell.row)
+           dest_info->cell.row--;
+
+         if (dest_info->cell.row != source_info->row)
+           gtk_clist_row_move (GTK_CLIST (widget),
+                               source_info->row,
+                               dest_info->cell.row);
+         g_dataset_remove_data (context, "gtk-clist-drag-dest");
+       }
+    }
+}
+
+static void  
+gtk_clist_drag_data_get (GtkWidget        *widget,
+                        GdkDragContext   *context,
+                        GtkSelectionData *selection_data,
+                        guint             info,
+                        guint             time)
+{
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (selection_data != NULL);
+
+  if (selection_data->target ==
+      gdk_atom_intern ("gtk-clist-drag-reorder", FALSE))
+    {
+      GtkCListCellInfo *info;
+
+      info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+      if (info)
+       {
+         GtkCListCellInfo *ret_info;
+
+         ret_info = g_new (GtkCListCellInfo, 1);
+         ret_info->row = info->row;
+         ret_info->column = info->column;
+
+         gtk_selection_data_set (selection_data,
+                                 selection_data->target,
+                                 GTK_TYPE_POINTER,
+                                 (guchar *) ret_info,
+                                 sizeof (GtkCListCellInfo));
+       }
+      else
+       gtk_selection_data_set (selection_data, selection_data->target,
+                               GTK_TYPE_POINTER, NULL, 0);
+    }
+}
+
+static void
+draw_drag_highlight (GtkCList        *clist,
+                    GtkCListRow     *dest_row,
+                    gint             dest_row_number,
+                    GtkCListDragPos  drag_pos)
+{
+  gint y;
+
+  y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
+
+  switch (drag_pos)
+    {
+    case GTK_CLIST_DRAG_NONE:
+      break;
+    case GTK_CLIST_DRAG_AFTER:
+      y += clist->row_height + 1;
+    case GTK_CLIST_DRAG_BEFORE:
+      gdk_draw_line (clist->clist_window, clist->xor_gc,
+                    0, y, clist->clist_window_width, y);
+      break;
+    case GTK_CLIST_DRAG_INTO:
+      gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
+                         clist->clist_window_width - 1, clist->row_height);
+      break;
+    }
+}
+
+void
+gtk_clist_set_reorderable (GtkCList *clist, 
+                          gboolean  reorderable)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if ((GTK_CLIST_REORDERABLE(clist) != 0) == reorderable)
+    return;
+
+  widget = GTK_WIDGET (clist);
+
+  if (reorderable)
+    {
+      GTK_CLIST_SET_FLAG (clist, CLIST_REORDERABLE);
+      gtk_drag_dest_set (widget,
+                        GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+                        &clist_target_table, 1, GDK_ACTION_MOVE);
+    }
+  else
+    {
+      GTK_CLIST_UNSET_FLAG (clist, CLIST_REORDERABLE);
+      gtk_drag_dest_unset (GTK_WIDGET (clist));
+    }
+}
+
+void
+gtk_clist_set_use_drag_icons (GtkCList *clist,
+                             gboolean  use_icons)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if (use_icons != 0)
+    GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
+  else
+    GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
+}
+
+void
+gtk_clist_set_button_actions (GtkCList *clist,
+                             guint     button,
+                             guint8    button_actions)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+  
+  if (button <= MAX_BUTTON)
+    {
+      if (gdk_pointer_is_grabbed () || GTK_WIDGET_HAS_GRAB (clist))
+       {
+         remove_grab (clist);
+         clist->drag_button = 0;
+       }
+
+      if (clist->anchor >= 0 &&
+         clist->selection_mode == GTK_SELECTION_EXTENDED)
+       GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+
+      clist->button_actions[button] = button_actions;
+    }
+}
index 548f591f0fa71954ebd1201114b017b0b5d02f75..87fa02f424d02b28f7e71ac2feef4b17c4774acf 100644 (file)
@@ -36,14 +36,17 @@ extern "C" {
 /* clist flags */
 enum                    
 {
-  GTK_CLIST_IN_DRAG             = 1 << 0,
-  GTK_CLIST_DRAG_SELECTION      = 1 << 1,
-  GTK_CLIST_ROW_HEIGHT_SET      = 1 << 2,
-  GTK_CLIST_SHOW_TITLES         = 1 << 3,
-  GTK_CLIST_CHILD_HAS_FOCUS     = 1 << 4,
-  GTK_CLIST_ADD_MODE            = 1 << 5,
-  GTK_CLIST_AUTO_SORT           = 1 << 6,
-  GTK_CLIST_AUTO_RESIZE_BLOCKED = 1 << 7
+  GTK_CLIST_IN_DRAG             = 1 <<  0,
+  GTK_CLIST_ROW_HEIGHT_SET      = 1 <<  1,
+  GTK_CLIST_SHOW_TITLES         = 1 <<  2,
+  GTK_CLIST_CHILD_HAS_FOCUS     = 1 <<  3,
+  GTK_CLIST_ADD_MODE            = 1 <<  4,
+  GTK_CLIST_AUTO_SORT           = 1 <<  5,
+  GTK_CLIST_AUTO_RESIZE_BLOCKED = 1 <<  6,
+  GTK_CLIST_REORDERABLE         = 1 <<  7,
+  GTK_CLIST_USE_DRAG_ICONS      = 1 <<  8,
+  GTK_CLIST_DRAW_DRAG_LINE      = 1 <<  9,
+  GTK_CLIST_DRAW_DRAG_RECT      = 1 << 10
 }; 
 
 /* cell types */
@@ -56,6 +59,22 @@ typedef enum
   GTK_CELL_WIDGET
 } GtkCellType;
 
+typedef enum
+{
+  GTK_CLIST_DRAG_NONE,
+  GTK_CLIST_DRAG_BEFORE,
+  GTK_CLIST_DRAG_INTO,
+  GTK_CLIST_DRAG_AFTER
+} GtkCListDragPos;
+
+typedef enum
+{
+  GTK_BUTTON_IGNORED = 0,
+  GTK_BUTTON_SELECTS = 1 << 0,
+  GTK_BUTTON_DRAGS   = 1 << 1,
+  GTK_BUTTON_EXPANDS = 1 << 2
+} GtkButtonAction;
+
 #define GTK_TYPE_CLIST            (gtk_clist_get_type ())
 #define GTK_CLIST(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_CLIST, GtkCList))
 #define GTK_CLIST_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CLIST, GtkCListClass))
@@ -70,10 +89,13 @@ typedef enum
 #define GTK_CLIST_ROW_HEIGHT_SET(clist)    (GTK_CLIST_FLAGS (clist) & GTK_CLIST_ROW_HEIGHT_SET)
 #define GTK_CLIST_SHOW_TITLES(clist)       (GTK_CLIST_FLAGS (clist) & GTK_CLIST_SHOW_TITLES)
 #define GTK_CLIST_CHILD_HAS_FOCUS(clist)   (GTK_CLIST_FLAGS (clist) & GTK_CLIST_CHILD_HAS_FOCUS)
-#define GTK_CLIST_DRAG_SELECTION(clist)    (GTK_CLIST_FLAGS (clist) & GTK_CLIST_DRAG_SELECTION)
 #define GTK_CLIST_ADD_MODE(clist)          (GTK_CLIST_FLAGS (clist) & GTK_CLIST_ADD_MODE)
 #define GTK_CLIST_AUTO_SORT(clist)         (GTK_CLIST_FLAGS (clist) & GTK_CLIST_AUTO_SORT)
 #define GTK_CLIST_AUTO_RESIZE_BLOCKED(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_AUTO_RESIZE_BLOCKED)
+#define GTK_CLIST_REORDERABLE(clist)       (GTK_CLIST_FLAGS (clist) & GTK_CLIST_REORDERABLE)
+#define GTK_CLIST_USE_DRAG_ICONS(clist)    (GTK_CLIST_FLAGS (clist) & GTK_CLIST_USE_DRAG_ICONS)
+#define GTK_CLIST_DRAW_DRAG_LINE(clist)    (GTK_CLIST_FLAGS (clist) & GTK_CLIST_DRAW_DRAG_LINE)
+#define GTK_CLIST_DRAW_DRAG_RECT(clist)    (GTK_CLIST_FLAGS (clist) & GTK_CLIST_DRAW_DRAG_RECT)
 
 #define GTK_CLIST_ROW(_glist_) ((GtkCListRow *)((_glist_)->data))
 
@@ -98,6 +120,21 @@ typedef gint (*GtkCListCompareFunc) (GtkCList     *clist,
                                     gconstpointer ptr1,
                                     gconstpointer ptr2);
 
+typedef struct _GtkCListCellInfo GtkCListCellInfo;
+typedef struct _GtkCListDestInfo GtkCListDestInfo;
+
+struct _GtkCListCellInfo
+{
+  gint row;
+  gint column;
+};
+
+struct _GtkCListDestInfo
+{
+  GtkCListCellInfo cell;
+  GtkCListDragPos  insert_pos;
+};
+
 struct _GtkCList
 {
   GtkContainer container;
@@ -153,6 +190,14 @@ struct _GtkCList
   GList *undo_unselection;
   gint undo_anchor;
   
+  /* mouse buttons */
+  guint8 button_actions[5];
+
+  guint8 drag_button;
+
+  /* dnd */
+  GtkCListCellInfo click_cell;
+
   /* scroll adjustments */
   GtkAdjustment *hadjustment;
   GtkAdjustment *vadjustment;
@@ -236,6 +281,10 @@ struct _GtkCListClass
                                 GdkRectangle   *area,
                                 gint            row,
                                 GtkCListRow    *clist_row);
+  void   (*draw_drag_highlight) (GtkCList        *clist,
+                                GtkCListRow     *target_row,
+                                gint             target_row_number,
+                                GtkCListDragPos  drag_pos);
   void   (*clear)               (GtkCList       *clist);
   void   (*fake_unselect_all)   (GtkCList       *clist,
                                 gint            row);
@@ -257,6 +306,7 @@ struct _GtkCListClass
                                 GtkCListRow    *clist_row,
                                 gint            column,
                                 GtkRequisition *requisition);
+
 };
 
 struct _GtkCListColumn
@@ -407,6 +457,15 @@ void gtk_clist_set_shadow_type (GtkCList      *clist,
 void gtk_clist_set_selection_mode (GtkCList         *clist,
                                   GtkSelectionMode  mode);
 
+/* enable clists reorder ability */
+void gtk_clist_set_reorderable (GtkCList *clist,
+                               gboolean  reorderable);
+void gtk_clist_set_use_drag_icons (GtkCList *clist,
+                                  gboolean  use_icons);
+void gtk_clist_set_button_actions (GtkCList *clist,
+                                  guint     button,
+                                  guint8    button_actions);
+
 /* freeze all visual updates of the list, and then thaw the list after
  * you have made a number of changes and the updates wil occure in a
  * more efficent mannor than if you made them on a unfrozen list
index 0a4179df9c10b2a806c53f977e9120a3fc823f42..ec02c895c14ec88cd75233ceddd2b8dbebabd0bf 100644 (file)
@@ -25,6 +25,7 @@
 #include "gtkctree.h"
 #include "gtkbindings.h"
 #include "gtkmain.h"
+#include "gtkdnd.h"
 #include <gdk/gdkx.h>
 #include <gdk/gdkkeysyms.h>
 
                                     + (clist)->hoffset)
 #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
 
+static inline gint
+COLUMN_FROM_XPIXEL (GtkCList * clist,
+                   gint x)
+{
+  gint i, cx;
+
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].visible)
+      {
+       cx = clist->column[i].area.x + clist->hoffset;
+
+       if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
+           x <= (cx + clist->column[i].area.width + COLUMN_INSET))
+         return i;
+      }
+
+  /* no match */
+  return -1;
+}
+
 #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (((GtkObject*) (_widget_))->klass)
 #define CLIST_UNFROZEN(clist)     (((GtkCList*) (clist))->freeze_count == 0)
 #define CLIST_REFRESH(clist)    G_STMT_START { \
@@ -59,8 +80,6 @@ enum {
   ARG_INDENT,
   ARG_SPACING,
   ARG_SHOW_STUB,
-  ARG_REORDERABLE,
-  ARG_USE_DRAG_ICONS,
   ARG_LINE_STYLE,
   ARG_EXPANDER_STYLE
 };
@@ -78,10 +97,6 @@ static void gtk_ctree_realize           (GtkWidget      *widget);
 static void gtk_ctree_unrealize         (GtkWidget      *widget);
 static gint gtk_ctree_button_press      (GtkWidget      *widget,
                                         GdkEventButton *event);
-static gint gtk_ctree_button_release    (GtkWidget      *widget,
-                                        GdkEventButton *event);
-static gint gtk_ctree_button_motion     (GtkWidget      *widget, 
-                                        GdkEventMotion *event);
 static void ctree_attach_styles         (GtkCTree       *ctree,
                                         GtkCTreeNode   *node,
                                         gpointer        data);
@@ -122,11 +137,11 @@ static gint gtk_ctree_draw_lines        (GtkCTree       *ctree,
 static void draw_row                    (GtkCList       *clist,
                                         GdkRectangle   *area,
                                         gint            row,
-                                        GtkCListRow   *clist_row);
-static void draw_xor_line               (GtkCTree       *ctree);
-static void draw_xor_rect               (GtkCTree       *ctree);
-static void create_drag_icon            (GtkCTree       *ctree,
-                                        GtkCTreeRow    *row);
+                                        GtkCListRow    *clist_row);
+static void draw_drag_highlight         (GtkCList        *clist,
+                                        GtkCListRow     *dest_row,
+                                        gint             dest_row_number,
+                                        GtkCListDragPos  drag_pos);
 static void tree_draw_node              (GtkCTree      *ctree,
                                         GtkCTreeNode  *node);
 static void set_cell_contents           (GtkCList      *clist,
@@ -196,9 +211,6 @@ static void real_tree_select            (GtkCTree      *ctree,
 static void real_tree_unselect          (GtkCTree      *ctree,
                                         GtkCTreeNode  *node,
                                         gint           column);
-static void tree_toggle_selection       (GtkCTree      *ctree, 
-                                        GtkCTreeNode  *node, 
-                                        gint           column);
 static void real_tree_expand            (GtkCTree      *ctree,
                                         GtkCTreeNode  *node);
 static void real_tree_collapse          (GtkCTree      *ctree,
@@ -245,9 +257,6 @@ static gint real_insert_row             (GtkCList      *clist,
 static void real_remove_row             (GtkCList      *clist,
                                         gint           row);
 static void real_sort_list              (GtkCList      *clist);
-static void set_mouse_cursor           (GtkCTree       *ctree,
-                                        gboolean       enable);
-static void check_cursor               (GtkCTree       *ctree);
 static void cell_size_request           (GtkCList       *clist,
                                         GtkCListRow    *clist_row,
                                         gint            column,
@@ -258,6 +267,27 @@ static void column_auto_resize          (GtkCList       *clist,
                                         gint            old_width);
 static void auto_resize_columns         (GtkCList       *clist);
 
+
+static gboolean check_drag               (GtkCTree         *ctree,
+                                         GtkCTreeNode     *drag_source,
+                                         GtkCTreeNode     *drag_target,
+                                         GtkCListDragPos   insert_pos);
+static void gtk_ctree_drag_begin         (GtkWidget        *widget,
+                                         GdkDragContext   *context);
+static gint gtk_ctree_drag_motion        (GtkWidget        *widget,
+                                         GdkDragContext   *context,
+                                         gint              x,
+                                         gint              y,
+                                         guint             time);
+static void gtk_ctree_drag_data_received (GtkWidget        *widget,
+                                         GdkDragContext   *context,
+                                         gint              x,
+                                         gint              y,
+                                         GtkSelectionData *selection_data,
+                                         guint             info,
+                                         guint32           time);
+
+
 enum
 {
   TREE_SELECT_ROW,
@@ -269,26 +299,6 @@ enum
   LAST_SIGNAL
 };
 
-typedef void (*GtkCTreeSignal1) (GtkObject    *object,
-                                GtkCTreeNode *arg1,
-                                gint          arg2,
-                                gpointer      data);
-
-typedef void (*GtkCTreeSignal2) (GtkObject    *object,
-                                GtkCTreeNode *arg1,
-                                GtkCTreeNode *arg2,
-                                GtkCTreeNode *arg3,
-                                gpointer      data);
-
-typedef void (*GtkCTreeSignal3) (GtkObject    *object,
-                                GtkCTreeNode *arg1,
-                                gpointer      data);
-
-typedef void (*GtkCTreeSignal4) (GtkObject         *object,
-                                GtkCTreeExpansionType arg1,
-                                gpointer           data);
-
-
 static GtkCListClass *parent_class = NULL;
 static GtkContainerClass *container_class = NULL;
 static guint ctree_signals[LAST_SIGNAL] = {0};
@@ -354,14 +364,6 @@ gtk_ctree_class_init (GtkCTreeClass *klass)
                           GTK_TYPE_BOOL,
                           GTK_ARG_READWRITE,
                           ARG_SHOW_STUB);
-  gtk_object_add_arg_type ("GtkCTree::reorderable",
-                          GTK_TYPE_BOOL,
-                          GTK_ARG_READWRITE,
-                          ARG_REORDERABLE);
-  gtk_object_add_arg_type ("GtkCTree::use_drag_icons",
-                          GTK_TYPE_BOOL,
-                          GTK_ARG_READWRITE,
-                          ARG_USE_DRAG_ICONS);
   gtk_object_add_arg_type ("GtkCTree::line_style",
                           GTK_TYPE_CTREE_LINE_STYLE,
                           GTK_ARG_READWRITE,
@@ -422,8 +424,10 @@ gtk_ctree_class_init (GtkCTreeClass *klass)
   widget_class->realize = gtk_ctree_realize;
   widget_class->unrealize = gtk_ctree_unrealize;
   widget_class->button_press_event = gtk_ctree_button_press;
-  widget_class->button_release_event = gtk_ctree_button_release;
-  widget_class->motion_notify_event = gtk_ctree_button_motion;
+
+  widget_class->drag_begin = gtk_ctree_drag_begin;
+  widget_class->drag_motion = gtk_ctree_drag_motion;
+  widget_class->drag_data_received = gtk_ctree_drag_data_received;
 
   clist_class->select_row = real_select_row;
   clist_class->unselect_row = real_unselect_row;
@@ -433,6 +437,7 @@ gtk_ctree_class_init (GtkCTreeClass *klass)
   clist_class->selection_find = selection_find;
   clist_class->click_column = NULL;
   clist_class->draw_row = draw_row;
+  clist_class->draw_drag_highlight = draw_drag_highlight;
   clist_class->clear = real_clear;
   clist_class->select_all = real_select_all;
   clist_class->unselect_all = real_unselect_all;
@@ -534,12 +539,6 @@ gtk_ctree_set_arg (GtkObject      *object,
     case ARG_SHOW_STUB:
       gtk_ctree_set_show_stub (ctree, GTK_VALUE_BOOL (*arg));
       break;
-    case ARG_REORDERABLE:
-      gtk_ctree_set_reorderable (ctree, GTK_VALUE_BOOL (*arg));
-      break;
-    case ARG_USE_DRAG_ICONS:
-      gtk_ctree_set_use_drag_icons (ctree, GTK_VALUE_BOOL (*arg));
-      break;
     case ARG_LINE_STYLE:
       gtk_ctree_set_line_style (ctree, GTK_VALUE_ENUM (*arg));
       break;
@@ -577,12 +576,6 @@ gtk_ctree_get_arg (GtkObject      *object,
     case ARG_SHOW_STUB:
       GTK_VALUE_BOOL (*arg) = ctree->show_stub;
       break;
-    case ARG_REORDERABLE:
-      GTK_VALUE_BOOL (*arg) = ctree->reorderable;
-      break;
-    case ARG_USE_DRAG_ICONS:
-      GTK_VALUE_BOOL (*arg) = ctree->use_icons;
-      break;
     case ARG_LINE_STYLE:
       GTK_VALUE_ENUM (*arg) = ctree->line_style;
       break;
@@ -598,22 +591,22 @@ gtk_ctree_get_arg (GtkObject      *object,
 static void
 gtk_ctree_init (GtkCTree *ctree)
 {
-  ctree->drag_icon      = NULL;
+  GtkCList *clist;
+
+  GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_RECT);
+  GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_LINE);
+
+  clist = GTK_CLIST (ctree);
+
   ctree->tree_indent    = 20;
   ctree->tree_spacing   = 5;
   ctree->tree_column    = 0;
-  ctree->drag_row       = -1;
-  ctree->drag_source    = NULL;
-  ctree->drag_target    = NULL;
-  ctree->insert_pos     = GTK_CTREE_POS_AS_CHILD;
-  ctree->reorderable    = FALSE;
-  ctree->use_icons      = TRUE;
-  ctree->in_drag        = FALSE;
-  ctree->drag_rect      = FALSE;
   ctree->line_style     = GTK_CTREE_LINES_SOLID;
   ctree->expander_style = GTK_CTREE_EXPANDER_SQUARE;
   ctree->drag_compare   = NULL;
   ctree->show_stub      = TRUE;
+
+  clist->button_actions[0] |= GTK_BUTTON_EXPANDS;
 }
 
 static void
@@ -753,6 +746,7 @@ gtk_ctree_button_press (GtkWidget      *widget,
 {
   GtkCTree *ctree;
   GtkCList *clist;
+  gint button_actions;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
@@ -761,9 +755,13 @@ gtk_ctree_button_press (GtkWidget      *widget,
   ctree = GTK_CTREE (widget);
   clist = GTK_CLIST (widget);
 
+  button_actions = clist->button_actions[event->button - 1];
+
+  if (button_actions == GTK_BUTTON_IGNORED)
+    return FALSE;
+
   if (event->window == clist->clist_window)
     {
-      gboolean collapse_expand = FALSE;
       GtkCTreeNode *work;
       gint x;
       gint y;
@@ -776,566 +774,175 @@ gtk_ctree_button_press (GtkWidget      *widget,
       if (!gtk_clist_get_selection_info (clist, x, y, &row, &column))
        return FALSE;
 
-      if (event->button == 2)
-       ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y);
-
       work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
          
-      if (ctree->reorderable && event->button == 2 && !ctree->in_drag &&
-         clist->anchor == -1)
-       {
-         gdk_pointer_grab (event->window, FALSE,
-                           GDK_POINTER_MOTION_HINT_MASK |
-                           GDK_BUTTON2_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
-                           NULL, NULL, event->time);
-         gtk_grab_add (widget);
-         ctree->in_drag = TRUE;
-         ctree->drag_source = work;
-         ctree->drag_target = NULL;
-         gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 
-                                     None, None);
-         gdk_gc_set_dashes (clist->xor_gc, 0, "\2\2", 2);
-         return FALSE;
-       }
-      else if (event->button == 1 &&
-              (GTK_CTREE_ROW (work)->children &&
-               (event->type == GDK_2BUTTON_PRESS ||
-                ctree_is_hot_spot (ctree, work, row, x, y))))
+      if (button_actions & GTK_BUTTON_EXPANDS &&
+         (GTK_CTREE_ROW (work)->children && !GTK_CTREE_ROW (work)->is_leaf  &&
+          (event->type == GDK_2BUTTON_PRESS ||
+           ctree_is_hot_spot (ctree, work, row, x, y))))
        {
          if (GTK_CTREE_ROW (work)->expanded)
            gtk_ctree_collapse (ctree, work);
          else
            gtk_ctree_expand (ctree, work);
 
-         collapse_expand = TRUE;
-       }
-      if (event->button == 1)
-       {
-         gint old_row = clist->focus_row;
-         gboolean no_focus_row = FALSE;
-
-         switch (clist->selection_mode)
-           {
-           case GTK_SELECTION_MULTIPLE:
-           case GTK_SELECTION_SINGLE:
-             if (!collapse_expand)
-               break;
-
-             if (clist->focus_row == -1)
-               {
-                 old_row = row;
-                 no_focus_row = TRUE;
-               }
-                 
-             GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gdk_pointer_grab (clist->clist_window, FALSE,
-                               GDK_POINTER_MOTION_HINT_MASK |
-                               GDK_BUTTON1_MOTION_MASK |
-                               GDK_BUTTON_RELEASE_MASK,
-                               NULL, NULL, event->time);
-             gtk_grab_add (widget);
-
-             if (GTK_CLIST_ADD_MODE (clist))
-               {
-                 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
-                 if (GTK_WIDGET_HAS_FOCUS (widget))
-                   {
-                     gtk_widget_draw_focus (widget);
-                     gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                                 GDK_LINE_SOLID, 0, 0);
-                     clist->focus_row = row;
-                     gtk_widget_draw_focus (widget);
-                   }
-                 else
-                   {
-                     gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                                 GDK_LINE_SOLID, 0, 0);
-                     clist->focus_row = row;
-                   }
-               }
-             else if (row != clist->focus_row)
-               {
-                 if (GTK_WIDGET_HAS_FOCUS (widget))
-                   {
-                     gtk_widget_draw_focus (widget);
-                     clist->focus_row = row;
-                     gtk_widget_draw_focus (widget);
-                   }
-                 else
-                   clist->focus_row = row;
-               }
-
-             if (!GTK_WIDGET_HAS_FOCUS (widget))
-               gtk_widget_grab_focus (widget);
-
-             return FALSE;
-
-           default:
-             break;
-           }
+         return FALSE;
        }
     }
   return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
 }
 
-static gint
-gtk_ctree_button_motion (GtkWidget      *widget, 
-                        GdkEventMotion *event)
-{
-  GtkCTree *ctree;
-  GtkCList *clist;
-  gint x;
-  gint y;
-  gint row;
-  gint insert_pos = GTK_CTREE_POS_AS_CHILD;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  ctree = GTK_CTREE (widget);
-  clist = GTK_CLIST (widget);
-
-  if (GTK_CLIST_IN_DRAG (clist))
-    return  GTK_WIDGET_CLASS (parent_class)->motion_notify_event
-      (widget, event);
-
-  if (event->window == clist->clist_window && 
-      ctree->in_drag && ctree->reorderable)
-    {
-      GdkModifierType modmask;
-      gint root_x;
-      gint root_y;
-
-      x = event->x;
-      y = event->y;
-      if (event->is_hint)
-       gdk_window_get_pointer (event->window, &x, &y, NULL);
-
-      /* delayed drag start */
-      if (!ctree->drag_target &&
-         y >= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) &&
-         y <= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) + clist->row_height)
-       return 
-         GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
-
-      if (ctree->use_icons)
-       {
-         if (!ctree->drag_icon)
-           create_drag_icon (ctree, GTK_CTREE_ROW (ctree->drag_source));
-         else
-           {
-             gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
-             gdk_window_move (ctree->drag_icon, root_x - ctree->icon_width /2,
-                              root_y - ctree->icon_height);
-           }
-       }
-
-      /* out of bounds check */
-      if (x < 0 || y < -3 || x > clist->clist_window_width ||
-         y > clist->clist_window_height + 3 ||
-         y > ROW_TOP_YPIXEL (clist, clist->rows-1) + clist->row_height + 3)
-       {
-         if (ctree->drag_row >= 0)
-           {
-             if (ctree->drag_rect)
-               {
-                 draw_xor_rect (ctree);
-                 ctree->drag_rect = FALSE;
-               }
-             else
-               draw_xor_line (ctree);
-             ctree->drag_row = -1;
-           }
-         return 
-           (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) 
-           (widget, event);
-       }
-
-      row = ROW_FROM_YPIXEL (clist, y);
-
-      /* re-calculate target (mouse left the window) */
-      if (ctree->drag_target && ctree->drag_row == -1)
-       ctree->drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list,row));
-      
-      if (y < 0 || y > clist->clist_window_height || 
-         ROW_TOP_YPIXEL (clist, row + 1) > clist->clist_window_height
-         || row >= clist->rows)
-       return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
-         (widget, event);
-
-      if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4)
-       insert_pos = GTK_CTREE_POS_BEFORE;
-      else if (ROW_TOP_YPIXEL (clist, row) + clist->row_height - y 
-              < clist->row_height / 4)
-       insert_pos = GTK_CTREE_POS_AFTER;
-
-      if (row != ctree->drag_row || 
-         (row == ctree->drag_row && ctree->insert_pos != insert_pos))
-       {
-         if (insert_pos != GTK_CTREE_POS_AS_CHILD)
-           {
-             if (ctree->drag_row >= 0)
-               {
-                 if (ctree->drag_rect)
-                   {
-                     draw_xor_rect (ctree);
-                     ctree->drag_rect = FALSE;
-                   }
-                 else
-                   draw_xor_line (ctree);
-               }
-             ctree->insert_pos = insert_pos;
-             ctree->drag_target =
-               GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
-             ctree->drag_row = row;
-             draw_xor_line (ctree);
-             check_cursor(ctree);
-           }
-         else if (ctree->drag_target &&
-                  !GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
-           {
-             if (ctree->drag_row >= 0)
-               {
-                 if (ctree->drag_rect)
-                   draw_xor_rect (ctree);
-                 else
-                   draw_xor_line (ctree);
-               }
-             ctree->drag_rect = TRUE;
-             ctree->insert_pos = insert_pos;
-             ctree->drag_target =
-               GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
-             ctree->drag_row = row;
-             draw_xor_rect (ctree);
-             check_cursor(ctree);
-           }
-       }
-    }
-  return GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
-}
-
-static gint
-gtk_ctree_button_release (GtkWidget      *widget, 
-                         GdkEventButton *event)
-{
-  GtkCTree *ctree;
-  GtkCList *clist;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  ctree = GTK_CTREE (widget);
-  clist = GTK_CLIST (widget);
-
-  if (event->button == 2 && clist->anchor == -1)
-    {
-      gtk_grab_remove (widget);
-      gdk_pointer_ungrab (event->time);
-
-      ctree->in_drag = FALSE;
-
-      set_mouse_cursor(ctree, TRUE);
-
-      if (ctree->use_icons && ctree->drag_icon)
-       {
-         gdk_window_destroy (ctree->drag_icon);
-         ctree->drag_icon = NULL;
-       }
-
-      if (ctree->drag_row >= 0)
-       {
-         if (ctree->drag_rect)
-           {
-             draw_xor_rect (ctree);
-             ctree->drag_rect = FALSE;
-           }
-         else
-           draw_xor_line (ctree);
-         ctree->drag_row = -1;
-       }
-
-      if (GTK_CLIST_ADD_MODE (clist))
-       gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
-      else
-       gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                   GDK_LINE_SOLID, 0, 0);
-
-      /* nop if out of bounds / source == target */
-      if (event->x < 0 || event->y < -3 ||
-         event->x > clist->clist_window_width ||
-         event->y > clist->clist_window_height + 3 ||
-         ctree->drag_target == ctree->drag_source ||
-         !ctree->drag_target)
-       return GTK_WIDGET_CLASS (parent_class)->button_release_event
-         (widget, event);
-
-      if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
-         !gtk_ctree_is_ancestor (ctree, ctree->drag_source,
-                                 ctree->drag_target))
-       {
-         if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
-           {
-             if (GTK_CTREE_ROW (ctree->drag_target)->sibling != 
-                 ctree->drag_source)
-               if (!ctree->drag_compare ||
-                   ctree->drag_compare (ctree,
-                                        ctree->drag_source,
-                                        GTK_CTREE_ROW (ctree->drag_target)->parent,
-                                        GTK_CTREE_ROW (ctree->drag_target)->sibling))
-                 gtk_signal_emit (GTK_OBJECT (ctree), 
-                                  ctree_signals[TREE_MOVE],
-                                  ctree->drag_source,
-                                  GTK_CTREE_ROW (ctree->drag_target)->parent,
-                                  GTK_CTREE_ROW (ctree->drag_target)->sibling);
-           }
-         else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
-           {
-             if (GTK_CTREE_ROW (ctree->drag_source)->sibling != 
-                 ctree->drag_target)
-               if (!ctree->drag_compare ||
-                   ctree->drag_compare (ctree,
-                                        ctree->drag_source,
-                                        GTK_CTREE_ROW (ctree->drag_target)->parent,
-                                        ctree->drag_target))
-                 gtk_signal_emit (GTK_OBJECT (ctree), 
-                                  ctree_signals[TREE_MOVE],
-                                  ctree->drag_source,
-                                  GTK_CTREE_ROW (ctree->drag_target)->parent,
-                                  ctree->drag_target);
-           }
-         else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
-           {
-             if (GTK_CTREE_ROW (ctree->drag_target)->children !=
-                 ctree->drag_source)
-               if (!ctree->drag_compare ||
-                   ctree->drag_compare (ctree,
-                                        ctree->drag_source,
-                                        ctree->drag_target,
-                                        GTK_CTREE_ROW (ctree->drag_target)->children))
-                 gtk_signal_emit (GTK_OBJECT (ctree), 
-                                  ctree_signals[TREE_MOVE],
-                                  ctree->drag_source,
-                                  ctree->drag_target,
-                                  GTK_CTREE_ROW (ctree->drag_target)->children);
-           }
-       }
-      ctree->drag_source = NULL;
-      ctree->drag_target = NULL;
-    }
-  else if (event->button == 1 && GTK_CLIST_DRAG_SELECTION (clist) &&
-          (clist->selection_mode == GTK_SELECTION_SINGLE ||
-           clist->selection_mode == GTK_SELECTION_MULTIPLE))
-    {
-      gint row;
-      gint column;
-      GtkCTreeNode *work;
-
-      if (gtk_clist_get_selection_info
-         (clist, event->x, event->y, &row, &column))
-       {
-         if (clist->anchor == clist->focus_row &&
-             (work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row))))
-           tree_toggle_selection (ctree, work, column);
-       }
-      clist->anchor = -1;
-    }
-  return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
-}
-
 static void
-create_drag_icon (GtkCTree    *ctree,
-                 GtkCTreeRow *row)
+draw_drag_highlight (GtkCList        *clist,
+                    GtkCListRow     *dest_row,
+                    gint             dest_row_number,
+                    GtkCListDragPos  drag_pos)
 {
-  GtkCList *clist;
-  GtkWidget *widget;
-  GdkWindow *window = NULL;
-  GdkWindowAttr attributes;
-  gint attributes_mask;
-  GdkPixmap *pixmap;
-  GdkBitmap *mask;
-  GdkModifierType modmask;
-  gint root_x;
-  gint root_y;
-
-  clist  = GTK_CLIST (ctree);
-  widget = GTK_WIDGET (ctree);
-
-  if (!(pixmap = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->pixmap))
-    return;
-  mask = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->mask;
-
-  gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
-  gdk_window_get_size (pixmap, &ctree->icon_width, &ctree->icon_height);
-
-  attributes.window_type = GDK_WINDOW_TEMP;
-  attributes.x = root_x - ctree->icon_width / 2;
-  attributes.y = root_y - ctree->icon_height;
-  attributes.width = ctree->icon_width;
-  attributes.height = ctree->icon_height;
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
-  attributes.event_mask = gtk_widget_get_events (widget);
-
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-
-  window = gdk_window_new (widget->window, &attributes, attributes_mask);
-  gdk_window_set_back_pixmap (window, pixmap, FALSE);
-  if (mask)
-    gdk_window_shape_combine_mask (window, mask, 0, 0);
-  gdk_window_show (window);
-
-  ctree->drag_icon = window;
-}
-
-static void
-draw_xor_line (GtkCTree *ctree)
-{
-  GtkCList *clist;
+  GtkCTree *ctree;
+  GdkPoint points[4];
   gint level;
+  gint i;
   gint y = 0;
 
-  clist = GTK_CLIST (ctree);
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CTREE (clist));
 
-  level = GTK_CTREE_ROW (ctree->drag_target)->level;
+  ctree = GTK_CTREE (clist);
 
-  if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
-    y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
-  else 
-    y = ROW_TOP_YPIXEL (clist, ctree->drag_row) - 1;
+  level = ((GtkCTreeRow *)(dest_row))->level;
 
-  if (clist->column[ctree->tree_column].visible)
-    switch (clist->column[ctree->tree_column].justification)
-      {
-      case GTK_JUSTIFY_CENTER:
-      case GTK_JUSTIFY_FILL:
-      case GTK_JUSTIFY_LEFT:
-       if (ctree->tree_column > 0)
-         gdk_draw_line (clist->clist_window, clist->xor_gc, 
-                        COLUMN_LEFT_XPIXEL(clist, 0), y,
-                        COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
-                        clist->column[ctree->tree_column - 1].area.width, y);
+  y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
+
+  switch (drag_pos)
+    {
+    case GTK_CLIST_DRAG_NONE:
+      break;
+    case GTK_CLIST_DRAG_AFTER:
+      y += clist->row_height + 1;
+    case GTK_CLIST_DRAG_BEFORE:
       
-       gdk_draw_line (clist->clist_window, clist->xor_gc, 
-                      COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + 
-                      ctree->tree_indent * level -
-                      (ctree->tree_indent - PM_SIZE) / 2, y,
-                      GTK_WIDGET (ctree)->allocation.width, y);
-       break;
-      case GTK_JUSTIFY_RIGHT:
-       if (ctree->tree_column < clist->columns - 1)
-         gdk_draw_line (clist->clist_window, clist->xor_gc, 
-                        COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), y,
-                        COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
-                        clist->column[clist->columns - 1].area.width, y);
+      if (clist->column[ctree->tree_column].visible)
+       switch (clist->column[ctree->tree_column].justification)
+         {
+         case GTK_JUSTIFY_CENTER:
+         case GTK_JUSTIFY_FILL:
+         case GTK_JUSTIFY_LEFT:
+           if (ctree->tree_column > 0)
+             gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                            COLUMN_LEFT_XPIXEL(clist, 0), y,
+                            COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1)+
+                            clist->column[ctree->tree_column - 1].area.width,
+                            y);
+
+           gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                          COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + 
+                          ctree->tree_indent * level -
+                          (ctree->tree_indent - PM_SIZE) / 2, y,
+                          GTK_WIDGET (ctree)->allocation.width, y);
+           break;
+         case GTK_JUSTIFY_RIGHT:
+           if (ctree->tree_column < clist->columns - 1)
+             gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                            COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1),
+                            y,
+                            COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
+                            clist->column[clist->columns - 1].area.width, y);
       
+           gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                          0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
+                          + clist->column[ctree->tree_column].area.width -
+                          ctree->tree_indent * level +
+                          (ctree->tree_indent - PM_SIZE) / 2, y);
+           break;
+         }
+      else
        gdk_draw_line (clist->clist_window, clist->xor_gc, 
-                      0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
-                      + clist->column[ctree->tree_column].area.width -
-                      ctree->tree_indent * level +
-                      (ctree->tree_indent - PM_SIZE) / 2, y);
-       break;
-      }
-  else
-    gdk_draw_line (clist->clist_window, clist->xor_gc, 
-                  0, y, clist->clist_window_width, y);
-}
-
-static void
-draw_xor_rect (GtkCTree *ctree)
-{
-  GtkCList *clist;
-  GdkPoint points[4];
-  guint level;
-  gint i;
-  gint y;
-
-  clist = GTK_CLIST (ctree);
-
-  level = GTK_CTREE_ROW (ctree->drag_target)->level;
-
-  y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
+                      0, y, clist->clist_window_width, y);
+      break;
+    case GTK_CLIST_DRAG_INTO:
+      y = ROW_TOP_YPIXEL (clist, dest_row_number) + clist->row_height;
 
-  if (clist->column[ctree->tree_column].visible)
-    switch (clist->column[ctree->tree_column].justification)
-      {
-      case GTK_JUSTIFY_CENTER:
-      case GTK_JUSTIFY_FILL:
-      case GTK_JUSTIFY_LEFT:
-       points[0].x =  COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + 
-         ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
-       points[0].y = y;
-       points[3].x = points[0].x;
-       points[3].y = y - clist->row_height - 1;
-       points[1].x = clist->clist_window_width - 1;
-       points[1].y = points[0].y;
-       points[2].x = points[1].x;
-       points[2].y = points[3].y;
-
-       for (i = 0; i < 3; i++)
-         gdk_draw_line (clist->clist_window, clist->xor_gc,
-                        points[i].x, points[i].y,
-                        points[i+1].x, points[i+1].y);
-
-       if (ctree->tree_column > 0)
+      if (clist->column[ctree->tree_column].visible)
+       switch (clist->column[ctree->tree_column].justification)
          {
-           points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
-             clist->column[ctree->tree_column - 1].area.width ;
+         case GTK_JUSTIFY_CENTER:
+         case GTK_JUSTIFY_FILL:
+         case GTK_JUSTIFY_LEFT:
+           points[0].x =  COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + 
+             ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
            points[0].y = y;
            points[3].x = points[0].x;
            points[3].y = y - clist->row_height - 1;
-           points[1].x = 0;
+           points[1].x = clist->clist_window_width - 1;
            points[1].y = points[0].y;
-           points[2].x = 0;
+           points[2].x = points[1].x;
            points[2].y = points[3].y;
 
            for (i = 0; i < 3; i++)
              gdk_draw_line (clist->clist_window, clist->xor_gc,
-                            points[i].x, points[i].y, points[i+1].x, 
-                            points[i+1].y);
-         }
-       break;
-      case GTK_JUSTIFY_RIGHT:
-       points[0].x =  COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - 
-         ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2  +
-         clist->column[ctree->tree_column].area.width;
-       points[0].y = y;
-       points[3].x = points[0].x;
-       points[3].y = y - clist->row_height - 1;
-       points[1].x = 0;
-       points[1].y = points[0].y;
-       points[2].x = 0;
-       points[2].y = points[3].y;
-
-       for (i = 0; i < 3; i++)
-         gdk_draw_line (clist->clist_window, clist->xor_gc,
-                        points[i].x, points[i].y,
-                        points[i+1].x, points[i+1].y);
-
-       if (ctree->tree_column < clist->columns - 1)
-         {
-           points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1);
+                            points[i].x, points[i].y,
+                            points[i+1].x, points[i+1].y);
+
+           if (ctree->tree_column > 0)
+             {
+               points[0].x = COLUMN_LEFT_XPIXEL(clist,
+                                                ctree->tree_column - 1) +
+                 clist->column[ctree->tree_column - 1].area.width ;
+               points[0].y = y;
+               points[3].x = points[0].x;
+               points[3].y = y - clist->row_height - 1;
+               points[1].x = 0;
+               points[1].y = points[0].y;
+               points[2].x = 0;
+               points[2].y = points[3].y;
+
+               for (i = 0; i < 3; i++)
+                 gdk_draw_line (clist->clist_window, clist->xor_gc,
+                                points[i].x, points[i].y, points[i+1].x, 
+                                points[i+1].y);
+             }
+           break;
+         case GTK_JUSTIFY_RIGHT:
+           points[0].x =  COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - 
+             ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 +
+             clist->column[ctree->tree_column].area.width;
            points[0].y = y;
            points[3].x = points[0].x;
            points[3].y = y - clist->row_height - 1;
-           points[1].x = clist->clist_window_width - 1;
+           points[1].x = 0;
            points[1].y = points[0].y;
-           points[2].x = points[1].x;
+           points[2].x = 0;
            points[2].y = points[3].y;
 
            for (i = 0; i < 3; i++)
              gdk_draw_line (clist->clist_window, clist->xor_gc,
                             points[i].x, points[i].y,
                             points[i+1].x, points[i+1].y);
+
+           if (ctree->tree_column < clist->columns - 1)
+             {
+               points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column +1);
+               points[0].y = y;
+               points[3].x = points[0].x;
+               points[3].y = y - clist->row_height - 1;
+               points[1].x = clist->clist_window_width - 1;
+               points[1].y = points[0].y;
+               points[2].x = points[1].x;
+               points[2].y = points[3].y;
+
+               for (i = 0; i < 3; i++)
+                 gdk_draw_line (clist->clist_window, clist->xor_gc,
+                                points[i].x, points[i].y,
+                                points[i+1].x, points[i+1].y);
+             }
+           break;
          }
-       break;
-      }      
-  else
-    gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
-                       0, y - clist->row_height,
-                       clist->clist_window_width - 1, clist->row_height);
+      else
+       gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                           0, y - clist->row_height,
+                           clist->clist_window_width - 1, clist->row_height);
+      break;
+    }
 }
 
 static gint
@@ -3748,42 +3355,6 @@ real_tree_unselect (GtkCTree     *ctree,
   tree_draw_node (ctree, node);
 }
 
-static void
-tree_toggle_selection (GtkCTree     *ctree,
-                      GtkCTreeNode *node,
-                      gint          column)
-{
-  GtkCList *clist;
-  
-  g_return_if_fail (ctree != NULL);
-  g_return_if_fail (GTK_IS_CTREE (ctree));
-
-  clist = GTK_CLIST (ctree);
-
-  switch (clist->selection_mode)
-    {
-    case GTK_SELECTION_SINGLE:
-    case GTK_SELECTION_MULTIPLE:
-      if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
-       gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], 
-                        node, column);
-      else if (node && GTK_CTREE_ROW (node)->row.selectable)
-       gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], 
-                        node, column);
-      break;
-
-    case GTK_SELECTION_BROWSE:
-      if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL &&
-         GTK_CTREE_ROW (node)->row.selectable)
-       gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], 
-                        node, column);
-      break;
-
-    case GTK_SELECTION_EXTENDED:
-      break;
-    }
-}
-
 static void
 select_row_recursive (GtkCTree     *ctree, 
                      GtkCTreeNode *node, 
@@ -4276,13 +3847,6 @@ real_clear (GtkCList *clist)
 
   ctree = GTK_CTREE (clist);
 
-  ctree->drag_row       = -1;
-  ctree->drag_rect      = FALSE;
-  ctree->in_drag        = FALSE;
-  ctree->drag_source    = NULL;
-  ctree->drag_target    = NULL;
-  ctree->drag_icon      = NULL;
-
   /* remove all rows */
   work = GTK_CTREE_NODE (clist->row_list);
   clist->row_list = NULL;
@@ -5186,7 +4750,7 @@ gtk_ctree_node_set_shift (GtkCTree     *ctree,
 void
 gtk_ctree_node_set_selectable (GtkCTree     *ctree,
                               GtkCTreeNode *node,
-                              gboolean     selectable)
+                              gboolean      selectable)
 {
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
@@ -5208,7 +4772,7 @@ gtk_ctree_node_set_selectable (GtkCTree     *ctree,
        {
          if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
            {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
+             clist->drag_button = 0;
              gtk_grab_remove (GTK_WIDGET (clist));
              gdk_pointer_ungrab (GDK_CURRENT_TIME);
              if (clist->htimer)
@@ -5687,14 +5251,6 @@ gtk_ctree_set_spacing (GtkCTree *ctree,
     CLIST_REFRESH (ctree);
 }
 
-void
-gtk_ctree_show_stub (GtkCTree *ctree,
-                    gboolean  show_stub)
-{
-  g_message ("gtk_ctree_show_stub() is deprecated");
-  gtk_ctree_set_show_stub (ctree, show_stub);
-}
-
 void
 gtk_ctree_set_show_stub (GtkCTree *ctree, 
                         gboolean  show_stub)
@@ -5718,29 +5274,6 @@ gtk_ctree_set_show_stub (GtkCTree *ctree,
     }
 }
 
-void
-gtk_ctree_set_reorderable (GtkCTree *ctree, 
-                          gboolean  reorderable)
-{
-  g_return_if_fail (ctree != NULL);
-  g_return_if_fail (GTK_IS_CTREE (ctree));
-
-  ctree->reorderable = reorderable;
-}
-
-void
-gtk_ctree_set_use_drag_icons (GtkCTree *ctree,
-                             gboolean  use_icons)
-{
-  g_return_if_fail (ctree != NULL);
-  g_return_if_fail (GTK_IS_CTREE (ctree));
-
-  if (ctree->use_icons == (use_icons != 0))
-    return;
-
-  ctree->use_icons = (use_icons != 0);
-}
-
 void 
 gtk_ctree_set_line_style (GtkCTree          *ctree, 
                          GtkCTreeLineStyle  line_style)
@@ -6195,73 +5728,375 @@ gtk_ctree_set_drag_compare_func (GtkCTree                *ctree,
   ctree->drag_compare = cmp_func;
 }
 
+static gboolean
+check_drag (GtkCTree        *ctree,
+           GtkCTreeNode    *drag_source,
+           GtkCTreeNode    *drag_target,
+           GtkCListDragPos  insert_pos)
+{
+  g_return_val_if_fail (ctree != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
+
+  if (drag_source && drag_source != drag_target &&
+      (!GTK_CTREE_ROW (drag_source)->children ||
+       !gtk_ctree_is_ancestor (ctree, drag_source, drag_target)))
+    {
+      switch (insert_pos)
+       {
+       case GTK_CLIST_DRAG_NONE:
+         return FALSE;
+       case GTK_CLIST_DRAG_AFTER:
+         if (GTK_CTREE_ROW (drag_target)->sibling != drag_source)
+           return (!ctree->drag_compare ||
+                   ctree->drag_compare (ctree,
+                                        drag_source,
+                                        GTK_CTREE_ROW (drag_target)->parent,
+                                        GTK_CTREE_ROW(drag_target)->sibling));
+         break;
+       case GTK_CLIST_DRAG_BEFORE:
+         if (GTK_CTREE_ROW (drag_source)->sibling != drag_target)
+           return (!ctree->drag_compare ||
+                   ctree->drag_compare (ctree,
+                                        drag_source,
+                                        GTK_CTREE_ROW (drag_target)->parent,
+                                        drag_target));
+         break;
+       case GTK_CLIST_DRAG_INTO:
+         if (!GTK_CTREE_ROW (drag_target)->is_leaf &&
+             GTK_CTREE_ROW (drag_target)->children != drag_source)
+           return (!ctree->drag_compare ||
+                   ctree->drag_compare (ctree,
+                                        drag_source,
+                                        drag_target,
+                                        GTK_CTREE_ROW (drag_target)->children));
+         break;
+       }
+    }
+  return FALSE;
+}
+
+
+
+/************************************/
 static void
-set_mouse_cursor (GtkCTree *ctree,
-                 gboolean  enable)
+drag_source_info_destroy (gpointer data)
 {
-  GdkCursor *cursor;
+  GtkCListCellInfo *info = data;
 
-  g_return_if_fail (ctree != NULL);
-  g_return_if_fail (GTK_IS_CTREE (ctree));
+  g_free (info);
+}
 
-  if (enable)
-    cursor = gdk_cursor_new (GDK_LEFT_PTR);
-  else
-    cursor = gdk_cursor_new (GDK_CIRCLE);
+static void
+drag_dest_info_destroy (gpointer data)
+{
+  GtkCListDestInfo *info = data;
 
-  gdk_window_set_cursor (GTK_CLIST (ctree)->clist_window, cursor);
-  gdk_cursor_destroy (cursor);
+  g_free (info);
 }
 
 static void
-check_cursor (GtkCTree *ctree)
+gtk_ctree_drag_begin (GtkWidget             *widget,
+                     GdkDragContext *context)
 {
-  g_return_if_fail (ctree != NULL);
-  g_return_if_fail (GTK_IS_CTREE (ctree));
+  GtkCList *clist;
+  GtkCTree *ctree;
+  GtkCListCellInfo *info;
 
-  if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
-      !gtk_ctree_is_ancestor (ctree, ctree->drag_source, ctree->drag_target))
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CTREE (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CLIST (widget);
+  ctree = GTK_CTREE (widget);
+
+  info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+  if (!info)
     {
-      if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
+      info = g_new (GtkCListCellInfo, 1);
+
+      if (clist->click_cell.row < 0)
+       clist->click_cell.row = 0;
+      else if (clist->click_cell.row >= clist->rows)
+       clist->click_cell.row = clist->rows - 1;
+      info->row = clist->click_cell.row;
+      info->column = clist->click_cell.column;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
+                              drag_source_info_destroy);
+    }
+
+  if (GTK_CLIST_USE_DRAG_ICONS (clist))
+    {
+      GtkCTreeNode *node;
+
+      node = GTK_CTREE_NODE (g_list_nth (clist->row_list, info->row));
+      if (node)
        {
-         if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
-             ctree->drag_source)
-           set_mouse_cursor
-             (ctree,
-              (!ctree->drag_compare ||
-               ctree->drag_compare
-               (ctree,
-                ctree->drag_source,
-                GTK_CTREE_ROW (ctree->drag_target)->parent,
-                GTK_CTREE_ROW (ctree->drag_target)->sibling)));
+         if (GTK_CELL_PIXTEXT
+             (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
+           {
+             gtk_drag_set_icon_pixmap
+               (context,
+                gtk_widget_get_colormap (widget),
+                GTK_CELL_PIXTEXT
+                (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap,
+                GTK_CELL_PIXTEXT
+                (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask,
+                -2, -2);
+             return;
+           }
        }
-      else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
+      gtk_drag_set_icon_default (context);
+    }
+}
+
+static gint
+gtk_ctree_drag_motion (GtkWidget      *widget,
+                      GdkDragContext *context,
+                      gint            x,
+                      gint            y,
+                      guint           time)
+{
+  GtkCList *clist;
+  GtkCTree *ctree;
+  gint row, column;
+  GtkCListDestInfo *dest_info;
+  gint h = 0;
+  gint insert_pos = GTK_CLIST_DRAG_NONE;
+  gint y_delta;
+
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
+
+  clist = GTK_CLIST (widget);
+  ctree = GTK_CTREE (widget);
+
+  if (gtk_drag_get_source_widget (context) != widget)
+    {
+      gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
+      return FALSE;
+    }
+
+  y -= (GTK_CONTAINER (widget)->border_width +
+       widget->style->klass->ythickness + clist->column_title_area.height);
+  row = ROW_FROM_YPIXEL (clist, y);
+
+  if (row >= clist->rows)
+    {
+      row = clist->rows - 1;
+      y = ROW_TOP_YPIXEL (clist, row) + clist->row_height;
+    }
+  if (row < -1)
+    row = -1;
+
+  x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness;
+  column = COLUMN_FROM_XPIXEL (clist, x);
+
+  if (row >= 0)
+    {
+      y_delta = y - ROW_TOP_YPIXEL (clist, row);
+      
+      if (GTK_CLIST_DRAW_DRAG_RECT(clist))
        {
-         if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
-             ctree->drag_target)
-           set_mouse_cursor
-             (ctree,
-              (!ctree->drag_compare ||
-               ctree->drag_compare
-               (ctree,
-                ctree->drag_source,
-                GTK_CTREE_ROW (ctree->drag_target)->parent,
-                ctree->drag_target)));
+         insert_pos = GTK_CLIST_DRAG_INTO;
+         h = clist->row_height / 4;
        }
-      else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
+      else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
+       {
+         insert_pos = GTK_CLIST_DRAG_BEFORE;
+         h = clist->row_height / 2;
+       }
+
+      if (GTK_CLIST_DRAW_DRAG_LINE(clist))
        {
-         if (GTK_CTREE_ROW (ctree->drag_target)->children !=
-             ctree->drag_source)
-           set_mouse_cursor
-             (ctree,
-              (!ctree->drag_compare ||
-               ctree->drag_compare
-               (ctree,
-                ctree->drag_source,
-                ctree->drag_target,
-                GTK_CTREE_ROW (ctree->drag_target)->children)));
+         if (y_delta < h)
+           insert_pos = GTK_CLIST_DRAG_BEFORE;
+         else if (clist->row_height - y_delta < h)
+           insert_pos = GTK_CLIST_DRAG_AFTER;
        }
     }
-  else
-    set_mouse_cursor(ctree, FALSE);
+
+  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+  if (!dest_info)
+    {
+      dest_info = g_new (GtkCListDestInfo, 1);
+         
+      dest_info->cell.row    = -1;
+      dest_info->cell.column = -1;
+      dest_info->insert_pos  = GTK_CLIST_DRAG_NONE;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
+                              drag_dest_info_destroy);
+    }
+
+  if (GTK_CLIST_REORDERABLE (clist))
+    {
+      GList *list;
+      GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+      list = context->targets;
+      while (list)
+       {
+         if (atom == GPOINTER_TO_INT (list->data))
+           break;
+         list = list->next;
+       }
+
+      if (list)
+       {
+         GtkCTreeNode *drag_source;
+         GtkCTreeNode *drag_target;
+
+         drag_source = GTK_CTREE_NODE (g_list_nth (clist->row_list,
+                                                   clist->click_cell.row));
+         drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
+
+         if (gtk_drag_get_source_widget (context) != widget ||
+             !check_drag (ctree, drag_source, drag_target, insert_pos))
+           {
+             if (dest_info->cell.row < 0)
+               {
+                 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
+                 return FALSE;
+               }
+             return TRUE;
+           }
+
+         if (row != dest_info->cell.row ||
+             (row == dest_info->cell.row &&
+              dest_info->insert_pos != insert_pos))
+           {
+             if (dest_info->cell.row >= 0)
+               GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
+                 (clist,
+                  g_list_nth (clist->row_list, dest_info->cell.row)->data,
+                  dest_info->cell.row, dest_info->insert_pos);
+
+             dest_info->insert_pos  = insert_pos;
+             dest_info->cell.row    = row;
+             dest_info->cell.column = column;
+
+             GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
+               (clist,
+                g_list_nth (clist->row_list, dest_info->cell.row)->data,
+                dest_info->cell.row, dest_info->insert_pos);
+
+             gdk_drag_status (context, context->suggested_action, time);
+           }
+         return TRUE;
+       }
+    }
+
+  dest_info->insert_pos  = insert_pos;
+  dest_info->cell.row    = row;
+  dest_info->cell.column = column;
+  return TRUE;
+}
+
+static void
+gtk_ctree_drag_data_received (GtkWidget        *widget,
+                             GdkDragContext   *context,
+                             gint              x,
+                             gint              y,
+                             GtkSelectionData *selection_data,
+                             guint             info,
+                             guint32           time)
+{
+  GtkCTree *ctree;
+  GtkCList *clist;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CTREE (widget));
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (selection_data != NULL);
+
+  ctree = GTK_CTREE (widget);
+  clist = GTK_CLIST (widget);
+
+  if (GTK_CLIST_REORDERABLE (clist) &&
+      gtk_drag_get_source_widget (context) == widget &&
+      selection_data->target ==
+      gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
+      selection_data->format == GTK_TYPE_POINTER &&
+      selection_data->length == sizeof (GtkCListCellInfo))
+    {
+      GtkCListCellInfo *source_info;
+      GtkCListDestInfo *dest_info;
+
+      source_info = (GtkCListCellInfo *)(selection_data->data);
+      dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+      if (dest_info && source_info)
+       {
+         GtkCTreeNode *source_node;
+         GtkCTreeNode *dest_node;
+         
+         source_node = GTK_CTREE_NODE (g_list_nth (clist->row_list,
+                                                   source_info->row));
+         dest_node = GTK_CTREE_NODE (g_list_nth (clist->row_list,
+                                                 dest_info->cell.row));
+
+         if (!source_info || !dest_info)
+           return;
+
+         switch (dest_info->insert_pos)
+           {
+           case GTK_CLIST_DRAG_NONE:
+             break;
+           case GTK_CLIST_DRAG_INTO:
+             if (check_drag (ctree, source_node, dest_node,
+                             dest_info->insert_pos))
+               gtk_ctree_move (ctree, source_node, dest_node,
+                               GTK_CTREE_ROW (dest_node)->children);
+             g_dataset_remove_data (context, "gtk-clist-drag-dest");
+             break;
+           case GTK_CLIST_DRAG_BEFORE:
+             if (check_drag (ctree, source_node, dest_node,
+                             dest_info->insert_pos))
+               gtk_ctree_move (ctree, source_node,
+                               GTK_CTREE_ROW (dest_node)->parent, dest_node);
+             g_dataset_remove_data (context, "gtk-clist-drag-dest");
+             break;
+           case GTK_CLIST_DRAG_AFTER:
+             if (check_drag (ctree, source_node, dest_node,
+                             dest_info->insert_pos))
+               gtk_ctree_move (ctree, source_node,
+                               GTK_CTREE_ROW (dest_node)->parent, 
+                               GTK_CTREE_ROW (dest_node)->sibling);
+             g_dataset_remove_data (context, "gtk-clist-drag-dest");
+             break;
+           }
+       }
+    }
+}
+
+/* deprecated*/
+void
+gtk_ctree_set_reorderable (GtkCTree *ctree, 
+                          gboolean  reorderable)
+{
+  g_return_if_fail (ctree != NULL);
+  g_return_if_fail (GTK_IS_CTREE (ctree));
+
+  gtk_clist_set_reorderable (GTK_CLIST (ctree), reorderable);
+}
+
+void
+gtk_ctree_set_use_drag_icons (GtkCTree *ctree,
+                             gboolean  use_icons)
+{
+  g_return_if_fail (ctree != NULL);
+  g_return_if_fail (GTK_IS_CTREE (ctree));
+
+  gtk_clist_set_use_drag_icons (GTK_CLIST (ctree), use_icons);
+}
+
+void
+gtk_ctree_show_stub (GtkCTree *ctree,
+                    gboolean  show_stub)
+{
+  g_message ("gtk_ctree_show_stub() is deprecated");
+  gtk_ctree_set_show_stub (ctree, show_stub);
 }
index 141316a14d2f86b6a88e2e019ddc626b9e186871..6f710911eb57e34bc76107752b3b7ba1a75652cb 100644 (file)
@@ -100,22 +100,11 @@ struct _GtkCTree
   GtkCList clist;
   
   GdkGC *lines_gc;
-  GdkWindow *drag_icon;
-  gint icon_width;
-  gint icon_height;
   
   gint tree_indent;
   gint tree_spacing;
   gint tree_column;
-  gint drag_row;
-  GtkCTreeNode *drag_source;
-  GtkCTreeNode *drag_target;
-  gint insert_pos;
-
-  guint reorderable    : 1;
-  guint use_icons      : 1;
-  guint in_drag        : 1;
-  guint drag_rect      : 1;
+
   guint line_style     : 2;
   guint expander_style : 2;
   guint show_stub      : 1;
@@ -418,10 +407,6 @@ void gtk_ctree_set_spacing           (GtkCTree                *ctree,
                                      gint                     spacing);
 void gtk_ctree_set_show_stub         (GtkCTree                *ctree, 
                                      gboolean                 show_stub);
-void gtk_ctree_set_reorderable       (GtkCTree                *ctree,
-                                     gboolean                 reorderable);
-void gtk_ctree_set_use_drag_icons    (GtkCTree                *ctree,
-                                     gboolean                 use_icons);
 void gtk_ctree_set_line_style        (GtkCTree                *ctree, 
                                      GtkCTreeLineStyle        line_style);
 void gtk_ctree_set_expander_style    (GtkCTree                *ctree, 
@@ -442,7 +427,10 @@ void gtk_ctree_sort_recursive                    (GtkCTree     *ctree,
 /* deprecated*/
 void gtk_ctree_show_stub             (GtkCTree                *ctree, 
                                      gboolean                 show_stub);
-
+void gtk_ctree_set_reorderable       (GtkCTree                *ctree,
+                                     gboolean                 reorderable);
+void gtk_ctree_set_use_drag_icons    (GtkCTree                *ctree,
+                                     gboolean                 use_icons);
 
 
 #ifdef __cplusplus
index 52f88989fb1f469db7e221fd0114dbb62dd9bca9..0cf829b367f28911afd818dc8153a196277bc6fa 100644 (file)
@@ -3722,6 +3722,11 @@ hide_titles_clist (GtkWidget *widget, gpointer data)
   gtk_clist_column_titles_hide (GTK_CLIST (data));
 }
 
+void toggle_reorderable (GtkWidget *widget, GtkCList *clist)
+{
+  gtk_clist_set_reorderable (clist, GTK_TOGGLE_BUTTON (widget)->active);
+}
+
 void
 select_clist (GtkWidget *widget,
              gint row, 
@@ -3995,6 +4000,7 @@ create_clist (void)
   GtkWidget *button;
   GtkWidget *separator;
   GtkWidget *scrolled_win;
+  GtkWidget *check;
 
   GtkWidget *undo_button;
   GtkWidget *label;
@@ -4097,6 +4103,12 @@ create_clist (void)
       gtk_signal_connect (GTK_OBJECT (undo_button), "clicked",
                           (GtkSignalFunc) undo_selection, (gpointer) clist);
 
+      check = gtk_check_button_new_with_label ("Reorderable");
+      gtk_signal_connect (GTK_OBJECT (check), "clicked",
+                         GTK_SIGNAL_FUNC (toggle_reorderable), clist);
+      gtk_box_pack_start (GTK_BOX (box2), check, FALSE, TRUE, 0);
+      gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (check), TRUE);
+
       label = gtk_label_new ("Selection Mode :");
       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
 
@@ -4112,18 +4124,6 @@ create_clist (void)
        * the rest of the clist configuration
        */
 
-      /*
-      gtk_signal_connect (GTK_OBJECT (clist), 
-                         "select_row",
-                         (GtkSignalFunc) select_clist, 
-                         undo_button);
-
-      gtk_signal_connect (GTK_OBJECT (clist), 
-                         "unselect_row",
-                         (GtkSignalFunc) unselect_clist, 
-                         undo_button);
-      */
-
       gtk_clist_set_row_height (GTK_CLIST (clist), 18);
       gtk_widget_set_usize (clist, -1, 300);
 
@@ -4275,74 +4275,6 @@ void after_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent,
           (parent) ? target1 : "nil", (sibling) ? target2 : "nil");
 }
 
-gint button_press (GtkCTree *ctree, GdkEventButton *event, gpointer data)
-{
-  gint row;
-  gint column;
-  GtkCTreeNode *work;
-  gint res;
-  
-  res = gtk_clist_get_selection_info (GTK_CLIST (ctree), event->x, event->y, 
-                                     &row, &column);
-  if (!res && event->button != 3)
-    return FALSE;
-
-  work = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row));
-
-  switch (event->button)
-    {
-    case 1:
-      if (GTK_CLIST (ctree)->selection_mode == GTK_SELECTION_MULTIPLE &&
-         event->state & GDK_SHIFT_MASK)
-       gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree),"button_press_event");
-      break;
-    case  2:
-      if (GTK_CTREE_ROW (work)->children && 
-         gtk_ctree_is_hot_spot (ctree, event->x, event->y))
-       {
-         if (GTK_CTREE_ROW (work)->expanded)
-           gtk_ctree_collapse_recursive (ctree, work);
-         else
-           gtk_ctree_expand_recursive (ctree, work);
-         after_press (ctree, NULL);
-         gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree),
-                                       "button_press_event");
-       }
-      break;
-    default:
-      break;
-    }
-  return FALSE;
-}
-
-gint button_release (GtkCTree *ctree, GdkEventButton *event, gpointer data)
-{
-  gint row;
-  gint column;
-  GtkCTreeNode *work;
-  gint res;
-  
-  res = gtk_clist_get_selection_info (GTK_CLIST (ctree), event->x, event->y, 
-                                     &row, &column);
-  if (!res || event->button != 1)
-    return FALSE;
-
-  work = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row));
-
-  if (GTK_CLIST (ctree)->selection_mode == GTK_SELECTION_MULTIPLE &&
-      event->state & GDK_SHIFT_MASK)
-    {
-      if (GTK_CTREE_ROW (work)->row.state == GTK_STATE_SELECTED) 
-           gtk_ctree_unselect_recursive (ctree, work);
-      else
-       gtk_ctree_select_recursive (ctree, work);
-      after_press (ctree, NULL);
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree), 
-                                   "button_release_event");
-    }
-  return FALSE;
-}
-
 void count_items (GtkCTree *ctree, GtkCTreeNode *list)
 {
   if (GTK_CTREE_ROW (list)->is_leaf)
@@ -4616,11 +4548,6 @@ void change_row_height (GtkWidget *widget, GtkCList *clist)
   gtk_clist_set_row_height (clist, GTK_ADJUSTMENT (widget)->value);
 }
 
-void toggle_reorderable (GtkWidget *widget, GtkCTree *ctree)
-{
-  gtk_ctree_set_reorderable (ctree, GTK_TOGGLE_BUTTON (widget)->active);
-}
-
 void set_background (GtkCTree *ctree, GtkCTreeNode *node, gpointer data)
 {
   GtkStyle *style = NULL;
@@ -4953,16 +4880,11 @@ void create_ctree (void)
       gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
       line_style = GTK_CTREE_LINES_DOTTED;
 
-      gtk_ctree_set_reorderable (ctree, TRUE);
       gtk_signal_connect (GTK_OBJECT (ctree), "click_column",
                          (GtkSignalFunc) ctree_click_column,
                          NULL);
-      gtk_signal_connect (GTK_OBJECT (ctree), "button_press_event",
-                         GTK_SIGNAL_FUNC (button_press), NULL);
       gtk_signal_connect_after (GTK_OBJECT (ctree), "button_press_event",
                                GTK_SIGNAL_FUNC (after_press), NULL);
-      gtk_signal_connect (GTK_OBJECT (ctree), "button_release_event",
-                         GTK_SIGNAL_FUNC (button_release), NULL);
       gtk_signal_connect_after (GTK_OBJECT (ctree), "button_release_event",
                                GTK_SIGNAL_FUNC (after_press), NULL);
       gtk_signal_connect_after (GTK_OBJECT (ctree), "tree_move",
index 52f88989fb1f469db7e221fd0114dbb62dd9bca9..0cf829b367f28911afd818dc8153a196277bc6fa 100644 (file)
@@ -3722,6 +3722,11 @@ hide_titles_clist (GtkWidget *widget, gpointer data)
   gtk_clist_column_titles_hide (GTK_CLIST (data));
 }
 
+void toggle_reorderable (GtkWidget *widget, GtkCList *clist)
+{
+  gtk_clist_set_reorderable (clist, GTK_TOGGLE_BUTTON (widget)->active);
+}
+
 void
 select_clist (GtkWidget *widget,
              gint row, 
@@ -3995,6 +4000,7 @@ create_clist (void)
   GtkWidget *button;
   GtkWidget *separator;
   GtkWidget *scrolled_win;
+  GtkWidget *check;
 
   GtkWidget *undo_button;
   GtkWidget *label;
@@ -4097,6 +4103,12 @@ create_clist (void)
       gtk_signal_connect (GTK_OBJECT (undo_button), "clicked",
                           (GtkSignalFunc) undo_selection, (gpointer) clist);
 
+      check = gtk_check_button_new_with_label ("Reorderable");
+      gtk_signal_connect (GTK_OBJECT (check), "clicked",
+                         GTK_SIGNAL_FUNC (toggle_reorderable), clist);
+      gtk_box_pack_start (GTK_BOX (box2), check, FALSE, TRUE, 0);
+      gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (check), TRUE);
+
       label = gtk_label_new ("Selection Mode :");
       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
 
@@ -4112,18 +4124,6 @@ create_clist (void)
        * the rest of the clist configuration
        */
 
-      /*
-      gtk_signal_connect (GTK_OBJECT (clist), 
-                         "select_row",
-                         (GtkSignalFunc) select_clist, 
-                         undo_button);
-
-      gtk_signal_connect (GTK_OBJECT (clist), 
-                         "unselect_row",
-                         (GtkSignalFunc) unselect_clist, 
-                         undo_button);
-      */
-
       gtk_clist_set_row_height (GTK_CLIST (clist), 18);
       gtk_widget_set_usize (clist, -1, 300);
 
@@ -4275,74 +4275,6 @@ void after_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent,
           (parent) ? target1 : "nil", (sibling) ? target2 : "nil");
 }
 
-gint button_press (GtkCTree *ctree, GdkEventButton *event, gpointer data)
-{
-  gint row;
-  gint column;
-  GtkCTreeNode *work;
-  gint res;
-  
-  res = gtk_clist_get_selection_info (GTK_CLIST (ctree), event->x, event->y, 
-                                     &row, &column);
-  if (!res && event->button != 3)
-    return FALSE;
-
-  work = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row));
-
-  switch (event->button)
-    {
-    case 1:
-      if (GTK_CLIST (ctree)->selection_mode == GTK_SELECTION_MULTIPLE &&
-         event->state & GDK_SHIFT_MASK)
-       gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree),"button_press_event");
-      break;
-    case  2:
-      if (GTK_CTREE_ROW (work)->children && 
-         gtk_ctree_is_hot_spot (ctree, event->x, event->y))
-       {
-         if (GTK_CTREE_ROW (work)->expanded)
-           gtk_ctree_collapse_recursive (ctree, work);
-         else
-           gtk_ctree_expand_recursive (ctree, work);
-         after_press (ctree, NULL);
-         gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree),
-                                       "button_press_event");
-       }
-      break;
-    default:
-      break;
-    }
-  return FALSE;
-}
-
-gint button_release (GtkCTree *ctree, GdkEventButton *event, gpointer data)
-{
-  gint row;
-  gint column;
-  GtkCTreeNode *work;
-  gint res;
-  
-  res = gtk_clist_get_selection_info (GTK_CLIST (ctree), event->x, event->y, 
-                                     &row, &column);
-  if (!res || event->button != 1)
-    return FALSE;
-
-  work = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row));
-
-  if (GTK_CLIST (ctree)->selection_mode == GTK_SELECTION_MULTIPLE &&
-      event->state & GDK_SHIFT_MASK)
-    {
-      if (GTK_CTREE_ROW (work)->row.state == GTK_STATE_SELECTED) 
-           gtk_ctree_unselect_recursive (ctree, work);
-      else
-       gtk_ctree_select_recursive (ctree, work);
-      after_press (ctree, NULL);
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree), 
-                                   "button_release_event");
-    }
-  return FALSE;
-}
-
 void count_items (GtkCTree *ctree, GtkCTreeNode *list)
 {
   if (GTK_CTREE_ROW (list)->is_leaf)
@@ -4616,11 +4548,6 @@ void change_row_height (GtkWidget *widget, GtkCList *clist)
   gtk_clist_set_row_height (clist, GTK_ADJUSTMENT (widget)->value);
 }
 
-void toggle_reorderable (GtkWidget *widget, GtkCTree *ctree)
-{
-  gtk_ctree_set_reorderable (ctree, GTK_TOGGLE_BUTTON (widget)->active);
-}
-
 void set_background (GtkCTree *ctree, GtkCTreeNode *node, gpointer data)
 {
   GtkStyle *style = NULL;
@@ -4953,16 +4880,11 @@ void create_ctree (void)
       gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
       line_style = GTK_CTREE_LINES_DOTTED;
 
-      gtk_ctree_set_reorderable (ctree, TRUE);
       gtk_signal_connect (GTK_OBJECT (ctree), "click_column",
                          (GtkSignalFunc) ctree_click_column,
                          NULL);
-      gtk_signal_connect (GTK_OBJECT (ctree), "button_press_event",
-                         GTK_SIGNAL_FUNC (button_press), NULL);
       gtk_signal_connect_after (GTK_OBJECT (ctree), "button_press_event",
                                GTK_SIGNAL_FUNC (after_press), NULL);
-      gtk_signal_connect (GTK_OBJECT (ctree), "button_release_event",
-                         GTK_SIGNAL_FUNC (button_release), NULL);
       gtk_signal_connect_after (GTK_OBJECT (ctree), "button_release_event",
                                GTK_SIGNAL_FUNC (after_press), NULL);
       gtk_signal_connect_after (GTK_OBJECT (ctree), "tree_move",